-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Remove Sync
requirement for Streaming
#117
Comments
So I'm not sure if this is a bug because technically it was intentional but I'm not sure how to get both working. Thanks for opening this. |
I have a similar case, I am using hyper client in a response stream, I get: the trait it works with 0.1.0-alpha.4 as mentioned in OP, and fails in 0.1.0-alpha.6. I am not sure how to work around that problem. |
So I believe using a channel should work as a temporary solution. @abdul-rehman0 would you be able to use a channel and a spawned task instead? |
@LucioFranco using a channel and spawn works for me, Thanks. Changed the following code: let client = Client::new(URL);
let response: PreferencesResponse = client.get(&[("to", "to")]).await.unwrap(); To: let (response_sender, response_receiver) = oneshot::channel::<PreferencesResponse>();
tokio::spawn(async move {
let client = Client::new(URL);
let response: PreferencesResponse = client.get(&[("to", "to")]).await.unwrap();
response_sender.send(response);
});
let response = response_receiver.await.unwrap(); |
Cool, I think this is probably the correct solution for now. I think it makes sense to cover both send and sync for now in the trait object since users can just use a channel. |
I think the above solution works well for this, so I will close this issue, feel free to reopen if you have any more questions. |
I do understand the workaround with channels, but I can't get my head around why the response stream needs to be @LucioFranco you say the change to Thanks for your help! These explanations will really help me in my (long) journey to enlightenment about rust async 😄 |
IIUC another way to fix is pub struct AlwaysSync<T>(T);
// SAFETY: This is essentially mutex, but without `lock()`.
// alternative justification: &AlwaysSync can't be upgrared to &T.
unsafe impl<T: Send> Sync for AlwaysSync<T> {}
impl AlwaysSync {
fn get_mut(&mut self) -> &mut T {
&mut self.0
}
fn get_mut_pinned(self: Pin<&mut Self>) -> Pin<&mut T> {
// SAFETY: just a pin projection
unsafe {Pin::map_unchecked_map(self, |s| &mut s.0)}
}
}
impl<T: Stream> Stream for AlwaysSync<T> {
type Item = T::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.get_mut_pinned().poll_next(cx)
}
} |
Internally, we |
I believe there is no need to require If I have enough time, I'll try to make a PR relaxing Sync bounds. |
@MikailBag Yeah, I am not sure how that adds up fully with regards to rust's safety rules, but personally I don't think its worth it. A channel works well. |
Thanks for taking the time to answer. Not sure I understand how it all fits together, but I guess I won't without looking at the code in more details. 😃 |
So after some considerations, I now think that this pattern/problem is pretty popular. I published a tiny crate: https://github.com/MikailBag/weird-mutex (will publish to crates-io if someone asks for that) that allows one to avoid Sync bounds without writing unsafe code. For example, see [https://github.com/hyperium/tonic/compare/master...MikailBag:unsync] for patch deleting Without patching Tonic code, one can wrap their streams in WeirdMutex and these streams will become Sync. |
@MikailBag There is already something like it: https://github.com/Actyx/sync_wrapper and I've send a PR: Actyx/sync_wrapper#1 |
I understand there's kind of a workaround now, but given that |
Also, did we ever get an answer for why a |
The original motivation for making @LucioFranco I think this trait bound can be removed on Tonic now. |
Yay! Can we reopen this issue and get rid of the trait bound? |
Sync
requirement for Streaming
Okay, I've reopened this, I will revisit this in the next release of tonic. |
Hm I'm not sure this is possible since hyper's Tonic uses tonic/tonic/src/transport/server/mod.rs Line 400 in 31936e0
|
One can always "upgrade" |
The |
Relevant commit in hyper hyperium/hyper@1d553e5 |
As we learned [in Tonic] bodies don't need to be `Sync` because they can only be polled from one thread at a time. This changes axum's bodies to no longer require `Sync` and makes `BoxBody` an alias for `UnsyncBoxBody<Bytes, axum::Error>`. [in Tonic]: hyperium/tonic#117
As we learned [in Tonic] bodies don't need to be `Sync` because they can only be polled from one thread at a time. This changes axum's bodies to no longer require `Sync` and makes `BoxBody` an alias for `UnsyncBoxBody<Bytes, axum::Error>`. [in Tonic]: hyperium/tonic#117
As we learned [in Tonic] bodies don't need to be `Sync` because they can only be polled from one thread at a time. This changes axum's bodies to no longer require `Sync` and makes `BoxBody` an alias for `UnsyncBoxBody<Bytes, axum::Error>`. [in Tonic]: hyperium/tonic#117
This is a followup to the conversation in #81 (comment) - I decided to create a new ticket to raise awareness.
Bug Report
Version
tonic = "0.1.0-alpha.5"
Platform
Darwin JayMBP-2.local 18.7.0 Darwin Kernel Version 18.7.0: Sat Oct 12 00:02:19 PDT 2019; root:xnu-4903.278.12~1/RELEASE_X86_64 x86_64
Description
In older releases, we're able to use non-Sync futures, like
hyper::client::ResponseFuture
to yield items in a streaming response. #84 added a Sync trait bound to the pinnedStream
trait object returned by the service impl. The following code works with the previous version of tonic:Works with 0.1.0-alpha.4
And the updated code now fails:
Fails with 0.1.0-alpha.5
Compile error
The text was updated successfully, but these errors were encountered: