-
Notifications
You must be signed in to change notification settings - Fork 312
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
Update extensions
to be cloneable
#395
Comments
Some thoughts from an interested user: Given new requirement on extensions, a breaking change then? You would apply the same to It sounds like you would With synchronous corollaries, we would typically not clone an With clone in play, the Would the next breaking release also be time to consider integrating |
So I think the real goal here should be to make |
I've shared my opinion on
|
@davidbarsky the issue is that task/thread-locals don't work with most channel backed offtask clients like hyper and tower-buffer. While ext do work with this setup. They couple data that is specific to the user within the request.
Agreed, but there are special cases like gRPC where we have total control over this and could probably pull of some sneak stuff related to this. Having parts be clonable would be a huge help here. |
I mean its your choice how to implement clone, if memcpy is cheap then do that if arc bump is cheap then do that? |
Sure. In those cases, I think the appropriate course of action is to implement an extension trait that performs a
My argument boils down that we don't need to settle for just making |
I'm not convinced that task locals are an acceptable substitute for FWIW, when Linkerd's retry code "clones" requests, we just clone the parts + body, and create new extensions. A lot of the data we store in extensions is specific to an individual instance of a request — e.g. we want to record latencies for retries separately. |
@hawkw that seems like it could easily be done in a clone where you basically clear the data 👍 |
Agreed, maybe roughly implement like it does in |
extensions
to be cloneableextensions
to be cloneable?
A few options here:
3 would be my personal recommendation–very flexible going forward and allows users who have no desire to have request extensions at all (most customers?) to have a cloneable request without worrying about it. We can also do a minimal |
I think we can implement |
I've been planning to write up some thoughts, summarizing this thread next week, so we can arrive at a decision. One thing I think is missing is analyzing what extensions tend to be used for. That would help with deciding if they can be clone, if they can't what should they be instead, etc. For example, in hyper the I imagine people likely stick loaded context into them, such as a User that was loaded from the DB, or even a DB handle. Are those clone? There's likely good examples on linkerd2, and in the AWS SDK, and others. Such an analysis would help in deciding "should we". |
We exclusively use |
I'm mainly using them with axum's Still, requiring |
The |
I think that making an |
I mean, we could also just "not write code that clones requests" to get that behavior. :) |
That seems like something that can't quite be defined as
A potential problem is that everything using |
Yeah, that's right. I only brought this up to say "we probably would not actually use a |
I think making extensions generic is going to make writing tower layers in tower-http much more painful than the benefit. @hawkw can you implement that new request logic in terms of a non clonable wrapper? Like you can wrap your extension in a way that it reconstructs on clone rather than reusing? |
Context: I was a heavy user of Extensions at a Cloudflare where I wrote HTTP and gRPC backends. I no longer have any active projects that use Extensions as my current workplace uses Dropshot. All the items we put into On the other hand, some items we put into response extensions are !Clone, but as far as I understand that is not being proposed. |
The Clone would apply to both Request and Response. |
At least for us, the main reason we want clone is to easily recreate |
Actix Web doesn't use any of the higher-level constructs from this crate, including |
Ok. I can always Arc the response extension types. |
+1 for a |
Alright, it looks like the consensus is to move forward and require An asideI was curious if we could use Oh well. |
extensions
to be cloneable?extensions
to be cloneable
PR is up: #634 Will merge quickly, in case you want to chime in, since target launch is Nov 15. |
some aspects of `linkerd-http-upgrade` are incompatible with the 1.0 interface of the `http` crate (_see: hyperium/http#395, linkerd/linkerd2#8733_). this new bound requiring that extensions must now be cloneable motivated me to read through this library's internals to gain a lucid understanding of how it works, in order to understand how to gracefully address [this](https://github.com/linkerd/linkerd2-proxy/blob/main/linkerd/http/upgrade/src/upgrade.rs#L25-L26) comment affixed to the `linkerd_http_upgrade::upgrade::Http11Upgrade` request/response extension: ```rust // Note: this relies on their only having been 2 Inner clones, so don't // implement `Clone` for this type. [sic] pub struct Http11Upgrade { half: Half, inner: Arc<Inner>, } ``` broadly, this library deals with some moderately arcane corners of the HTTP protocol family. the `Upgrade` header is not supported in HTTP/2, and was not yet introduced in HTTP/1.0, so it is a feature specific to HTTP/1.1. moreover, some behavior provided by this library falls into parts of the spec(s) that we `MUST` uphold, and isn't currently well documented. this branch includes a sequence of commits adding documentation and additional comments linking to, and quoting, the relevant parts of [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110). some links to RFC 7231, which was obsoleted by RFC 9110 since the original time of writing, are additionally updated. some comments also did not accurately describe internal logic, or included typos, and are also updated. --- * docs(http/upgrade): add crate-level docs, rfc link Signed-off-by: katelyn martin <[email protected]> * docs(http/upgrade): update link to obsolete rfc rfc 9110 obsoletes the following rfc's: 2818, 7230, 7231, 7232, 7233, 7235, 7538, 7615, and 7694. this updates a comment related to connection upgrade logic, linking to the current rfc, 9110. this information now lives in section 9.3.6, paragraph 12. Signed-off-by: katelyn martin <[email protected]> * nit(http/upgrade): update incorrect comment this function has since been renamed `halves()`. Signed-off-by: katelyn martin <[email protected]> * docs(http/upgrade): add comments to `wants_upgrade` this adds a comment additionally clarifying that HTTP/2 does not support upgrades. Signed-off-by: katelyn martin <[email protected]> * docs(http/upgrade): document `strip_connection_headers()` this function performs some important behavior that we MUST implement, as a proxy/intermediary. to help elucidate the mandated behavior expected of us by the HTTP/1 specification, add documentation comments noting the related passages from rfc 9110 § 7.6.1. Signed-off-by: katelyn martin <[email protected]> * nit(http/upgrade): fix typo in `Http11Upgrade` comment Signed-off-by: katelyn martin <[email protected]> * docs(http/upgrade): update incorrect comment this comment is not true. this commit updates it, reflecting the current state of the upgrade body's `Drop` logic. Signed-off-by: katelyn martin <[email protected]> --------- Signed-off-by: katelyn martin <[email protected]>
I propose that we move forward to allow
Request<B: Clone>
toimpl Clone
. The big blocker here is thatextensions
is not clonable. This could be fixed by making a AnyClone trait:The downside here is that all things you store in extensions is cloneable but I think this is a fair trade off since mostly its just information that could be thrown behind an arc or bytes.
cc @seanmonstar @carllerche @hawkw @davidbarsky
The text was updated successfully, but these errors were encountered: