-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feedback on attempting to port to 3.0.0-rc2 #870
Comments
@sosthene-nitrokey Thank you so much for taking the time to test this thoroughly. This is such great feedback that I can guarantee we need to address most of it and make an rc3. I have some personal health issues right now preventing me from deeply focusing on coding. I welcome all help with addressing these concerns via PRs.
Agree we need to address this. The main branch only did a builder, there config fields themselves are
I like where this is going. It never felt great to box everything up the way it is now. I'd also been thinking one could explore a completely generics-based chain that is only abstracted/boxed on the top level, but that might be a bit of a hairier change.
Yeah, ureq 2.x suffered badly from overexposing stuff that just had to break semver (like re-exporting other crates). Thus I been very reluctant to make all of the internal workings public, thinking that if someone needs the TcpConnector for their local needs, they can just copy-paste the code. In rc1 and still in rc2, I allowed myself exceptions to semver. Maybe it's a terrible idea, but we could potentially "carve out" exceptions to API stability by clearly marking it as such. Maybe the entire
When I started building 3.x, my entry point was that "The http-crate is the public API". It might be that I need to shift my thinking here. I would be open to a PR exporting these typestate variants under
Again, thank you so much for taking the time. I will not be able to look into these things myself right now, but I do promise to get to them eventually. I can however review PRs, so I welcome any help you can spare! |
I fully understand that concern, we are dealing with similar issues in our own libraries, which is why I suggested having a sibling crate (
I don't know if I would call this an exception to semver. Saying that a specific usage is a bug and its behaviour can change is something that is widely understood as being totally compatible with semver (as long as the types don't change and it's properly documented).
I don't like this idea. Splitting it out in its own crate would be make more sense. Worst case, it could also be possible (even with the current design), to just copy-paste the connectors in another crate, which could even be done by a third party that needs it (we would probably go this way).
There is a bit of a semver hazard in using a Thank for being open to the feedback! |
I just recalled that rustls used to have a similar idea, so there's at least some precedence, granted they are still on semver 0.x. My trouble with another crate is that I've been on the war path against increasing the dep count. In my view, maybe the main differentiating feature of ureq vs reqwest/static, is dep count. To reduce dep count, I've been considering rolling
True. I hadn't thought about the risk of them hijacking one of our names. If we do not Deref, we need to copy in like 7 fns we currently get via the Deref: If the http crate adds a way to mutate the query parameters, we probably still need to bump major, since I prefer to delegate to their way of doing it instead of maintaining parallel ways.
This is because I can't rebuild the query part of the uri without incurring the cost of allocation - something we try to avoid. Not ideal though. |
I do not understand why there is such a widespread concern about dep count in the Rust ecosystem. IHMO the real benchmark is:
Separating a single crate into multiple sub-crates does not change any of these metrics (especially if the crates live in the same git repo, even if they have different release cadence). And regarding the overall issue, I think it is worse to have multiple implementation of the same thing through copy-pasted code than having one more dependencies that implements a common pattern an is reused multiple times. In our specific case, the reason we use |
I hear you, but I see it slightly differently.
Is this an OK compromise?
Very interesting! Maybe this should be brought out in the docs? It's also very good input, because there been talks about "happy eyeballs" and other things that might require background threads to be spawned. |
Yes, that looks good!
What would that look like? Something like "
Would multithreading be the best implementation? the |
Cool. I'll rename the hoot crate today.
Yeah, that sounds almost perfect. I wouldn't even hide it behind feature flags, but say that the default configuration would never spawn background threads. The configuration options that will cause threads are clearly documented as such. This happens already today, but it's not brought out enough in the doc. https://github.com/algesten/ureq/blob/main/src/resolver.rs#L147
Yes, with async everything is possible.
This is an important reason I decided to rewrite to ureq 3. People come with PRs and suggestions that are really helpful, but I don't necessarily want to support them all myself. A |
It's a bit of a hairball to try and move |
Status on this:
And to address semver, there's a new |
Closing this, but if I missed something that should be addressed, let's make individual issues for that. Thanks! |
Hi,
We are using ureq in our PKCS#11 module, thank you for this reliable and simple library.
We recently had to fork ureq in our use to implement missing functionality we wanted to have, mainly TCP keepalive and automatically discarding old connections.
We hope the 3.x.x branch allowing separate "connectors" and "transport" and the fact that it already supports a max age for idle connections would permit us to migrate back to upstream.
I attempted to port our implementation to the 3.0.0-rc2, here are the challenges I encountered:
Config fields are private
This prevents implementing some of the functionality of the upstream
TcpConnector
in our own implementation (for example there is no way to read the nodelay configuration of the config, preventing of implementing the same functionality in other crates. Looking at themain
branch, it looks like this has been fixed, so this may be outdated.There would be benefits to not boxing the connectors
In the connector traits, the transports are boxed, preventing chained connectors to make use of specificities of the previous transport. Ideally for example, it would be possible to use the specific type of the previous transport. For example a TCP keepalive connector could just wrap or come after a TcpTransport, get its TCP stream, and enable Keepalive on it.
The way I would do it would use associated types for the transports, and make
chained
and not chained connectors part of the trait.With an implementation on tuples of many sizes through a macro:
You could still keep the
ChainedConnector
for oneConnector
+ a chain ofMiddleConnector<AnyTransport>
that could also be boxed.For connectors that may or may not "chain" like the SocksConnector followed by the TcpConnector, I would instead implement the
SocksConnector
as a:This type safety would allow for example a keepalive connector, which is much simpler that re-implementing all the functionality of the TcpConnector just to add that. It makes connectors much more composable.
The upstream connectors and transports are not public
This goes with the previous point. Building a custom chain of connectors could be simpler if the upstream connectors were public.
I understand that doing so would be a semver hazard, so maybe they should be in a separate crate (
ureq-utils
maybe?), to allow building on top of them, but allow the connectors to be more frequently updated.The typestate variants are not public
The types
WithoutBody
andWithBody
are not public (same for theConfig
scopes), which means it's not possible to write function that expect or return aRequestBuilder<WithoutBody>
.If you do not want these types to be public for semver reasons, would it be possible to still expose a type alias:
type RequestWithBody = RequestBuilder<WithBody>
,andtype RequestWithoutBody = RequestBuilder<WithoutBody>
, so that they be used in functions signatures?Thank you for the work on 3.0.0, this looks like it will certainly help ureq be more flexible!
If you want I can create dedicated issues (or even PRs) for the parts you think are worth it.
The text was updated successfully, but these errors were encountered: