-
Notifications
You must be signed in to change notification settings - Fork 293
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
[BUG] Rc<RefCell<wasm_bindgen_futures::Inner>>
cannot be sent between threads safely
#485
Comments
Unfortunately, while |
This article and the linked crate do something rather clever: https://logankeenan.com/posts/rust-axum-and-cloudflare-workers/
It's more of a hack than a solution. I browsed around and there don't seem to be any frameworks that work without futures that are |
Ok, great, I’ll check that out. Would be nice to have a generic solution. |
I think something slightly simpler might be possible, I added a generic macro, SendFuture(async move {
#fn_body
}).await where See example here which shouldn't work because workers-rs/worker-sandbox/src/fetch.rs Lines 20 to 39 in fca35f4
|
@avsaase I think this might be a cleaner direction for us to go to fix the remaining |
Marking things My problem with the |
There are more places where axum requires |
I'm just a little worried about having to go through wrap every single type. It feels time consuming and error prone. This addresses the issue right at the handler level.
I haven't run into this issue. What does not get highlighted?
I think for this we have |
I think adding this won't be too much work. I'm happy to give it a try.
Iirc it failed to highlight variable and function names. I'll give it another try with the proposed new macro and report back.
We have type safe wrappers around other |
I just worry that this will be hard to maintain, it also doesn't help the user in the case where they implement their own JS bindings. There are also other cases like: a430c23#diff-958be99384265b0bc1095abf1c900139f0b49da235617bdd1d080dc510ba731eR36 We manipulate JS types in a lot of our method implementations and have to re-factor them to avoid holding them across |
Hmm, I see how creating For advanced use cases like ours I think it's not too uncommon to want to use bindings like |
Would it not make sense to pass in |
I tried to get the example in the OP working by implementing
We have a worker with 100+ routes that uses a lot of kv stores and queues. To make this type safe we defined types like this: pub struct KvStoreClient<T> {
kv_store: KvStore,
_marker: std::marker::PhantomData<T>,
} with methods to perform operations in a type safe manner. All this is initialized at the top of |
Maybe the macro is the best solution after all. We'll have to |
I see, well I'm not opposed to implementing I think your issue with awaiting responses from // the scope here is sometimes necessary to make sure everything but the `SendFuture` is dropped before the `await`
let fut = {
worker::SendFuture::new(env.bucket("BUCKET")
.unwrap()
.list()
.execute())
};
let objects = fut.await.unwrap() Edit: or the whole handler can be made send using the macro I'm suggesting. |
I wonder if we could provide something like |
After thinking about this some more this I think there are two ways to go about this that will yield a good developer experience:
Note that it's possible to go with the second approach first and later implement the first without it being a breaking change.
I'm not exactly sure what you have in mind here but I think it falls somewhere in between these two extremes? I worry that it would require the user to add extra steps to their code that aren't really necessary if we pick one of the other two options. In any case, I think the current selection of types that satisfy the |
To be honest, I don't want to barge in, because you are having a very deep discussion on this already, and I simply don't know the best approach. But I believe you have to take in consideration that the bugs aren't always obvious and might seem even not related. A good example was a bug from @avsaase that was blocking him and he had no idea that worker::send was the fix, once I was able to spot with a helper macro
Things got a lot better, and send fixed it, but it was giving errors regarding traits implementations. Even with a notice, this might impose a hard challenge to anyone landing on workers-rs from other places... |
Agree that these error messages aren't great. What does the error message look like if https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html |
Here's the example I created when I was trying to debug a trait bound error on a middleware: use axum::{
body::Body,
extract::{Request, State},
http::HeaderMap,
middleware::{from_fn_with_state, Next},
response::Response,
routing::get,
};
use axum_cloudflare_adapter::{to_axum_request, to_worker_response};
use tower_service::Service;
#[worker::event(fetch)]
pub async fn main(
req: worker::Request,
env: worker::Env,
_ctx: worker::Context,
) -> worker::Result<worker::Response> {
let state = AppState {
kv: env.kv("kv_binding").unwrap(),
};
let axum_request = to_axum_request(req).await.unwrap();
let axum_response = axum::Router::new()
.route("/v0/test", get(|| async { "Hello, World!" }))
.layer(from_fn_with_state(
state.clone(),
move |state, req: Request, next| my_middleware(state, req.headers().clone(), req, next),
))
.with_state(state)
.call(axum_request)
.await?;
let worker_response = to_worker_response(axum_response).await.unwrap();
Ok(worker_response)
}
#[derive(Clone)]
struct AppState {
kv: worker::kv::KvStore,
}
unsafe impl Send for AppState {}
unsafe impl Sync for AppState {}
// #[axum_macros::debug_handler]
// #[worker::send]
async fn my_middleware(
State(state): State<AppState>,
_headers: HeaderMap,
request: Request,
next: Next,
) -> Response<Body> {
let value = state.kv.get("key").text().await.unwrap();
next.run(request).await
} With the
|
Is there an existing issue for this?
What version of
workers-rs
are you using?0.0.21
What version of
wrangler
are you using?2.13.0
Describe the bug
I see that you have recently added an example with axum. This is great! It would allow use of the entire tower ecosystem.
Env
implementsunsafe Send
which is perfect. But any attempt to use it fails. I cannot figure out how to make this work with any non-trivial example. Could you please share how you imagine this should work? For example, here I have extended the example to try and list R2 objects:However, we see this is not possible:
Steps To Reproduce
The text was updated successfully, but these errors were encountered: