option for `Send`-able `Session`
- Lingua principale
- Rust
- Stelle
- 889
- Fork
- 224
- Merge medio
- 9h 37m
- PR unite (30g)
- 20
Descrizione
Original title: `std::marker::Send` is not implemented for `Rc>`
## Expected Behavior
I am trying to use session object with `Redis` as the storage in a distributed system with `async-graphql` to set and delete session for `userid` but having issues with that because `actix-session` does not implement `Send` and cannot be moved across threads. It has type: `Rc>`. `async-graphql` requires that it has a `Send` trait.
## Current Behavior
Full compiler error message:
```rs
`Rc>` cannot be sent between threads safely
within `actix_session::Session`, the trait `std::marker::Send` is not implemented for `Rc>`rustc[E0277](https://doc.rust-lang.org/error-index.html#E0277)
graphql.rs(74, 23): required by a bound introduced by this call
lib.rs(1, 1): required because it appears within the type `actix_session::Session`
request.rs(91, 26): required by a bound in `Request::data`
`Rc>` cannot be shared between threads safely
within `actix_session::Session`, the trait `Sync` is not implemented for `Rc>`rustc[E0277](https://doc.rust-lang.org/error-index.html#E0277)
graphql.rs(74, 23): required by a bound introduced by this call
lib.rs(1, 1): required because it appears within the type `actix_session::Session`
```
## Possible Solution
Make Session type an `Arc/Mutex` rather than a `RefCell`
### Present workaround
```rs
use std::ops::Deref;
use actix_session::Session;
use send_wrapper::SendWrapper;
use uuid::Uuid;
use wither::bson::oid::ObjectId;
#[derive(Clone, Debug)]
struct Shared(pub Option>);
impl Shared {
pub fn new(v: T) -> Self {
Self(Some(SendWrapper::new(v)))
}
}
impl Deref for Shared {
type Target = T;
fn deref(&self) -> &Self::Target {
&*self.0.as_deref().unwrap()
}
}
type SessionShared = Shared;
#[derive(Debug, thiserror::Error)]
pub enum TypedSessionError {
#[error("Failed to parse data")]
ParsingFailure(#[from] serde_json::Error),
#[error(transparent)]
Unknown(#[from] anyhow::Error), // source and Display delegate to anyhow::Error
}
type TypedSessionResult = Result;
/*
This is somewhat like a hack: https://github.com/async-graphql/async-graphql/issues/426
Session is Session(Rc>) and probably okay to use
SendWrapper for now but having it implement Send would allow
using Arc/Mutex
*/
pub struct TypedSession(SessionShared);
impl TypedSession {
const USER_ID_KEY: &'static str = "user_id";
pub fn new(session: Session) -> Self {
Self(Shared::new(session))
}
pub fn renew(&self) {
self.0.renew();
}
pub fn insert_user_uuid(&self, user_id: Uuid) -> TypedSessionResult<()> {
self.0.insert(Self::USER_ID_KEY, user_id)?;
Ok(())
}
pub fn get_user_uuid(&self) -> TypedSessionResult> {
Ok(self.0.get::(Self::USER_ID_KEY)?)
}
pub fn clear(&self) {
self.0.clear()
}
}
## Steps to Reproduce (for bugs)
Try with async-graphql `GraphqlRequest` as shown below
```rs
#[post("/graphql")]
pub async fn index(
schema: web::Data,
req: HttpRequest,
gql_request: GraphQLRequest,
) -> GraphQLResponse {
let mut request = gql_request.into_inner();
let session = req.get_session();
request = request.data(session); // ---> This will fail because it expects it to have a Send Marker
schema.execute(request).await.into()
}
```
## Your Environment
Mac OS monterey macbook m1 max 14 inch 2021
* Rust Version (I.e, output of `rustc -V`): `Rust 1.61`
* Actix-* crate(s) Version: `actix-session: 0.6.2`
Sidenote:
Issues are also mentioned here:
- https://github.com/async-graphql/async-graphql/issues/867
- https://stackoverflow.com/questions/71455275/how-to-use-actix-redis-session-in-async-graphql-resolvers
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.