Skip to content

Commit 2ed9d9d

Browse files
50U10FCA7tyranron
andauthored
Clone Context on each new GraphQL operation in juniper_graphql_ws crate (#1369)
Co-authored-by: Kai Ren <tyranron@gmail.com>
1 parent 0a550a1 commit 2ed9d9d

9 files changed

Lines changed: 68 additions & 21 deletions

File tree

juniper_actix/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ All user visible changes to `juniper_actix` crate will be documented in this fil
1212

1313
- Switched to 0.4 version of [`actix-ws` crate]. ([#1366])
1414
- Bumped up [MSRV] to 1.88 due to [`actix-ws` crate] requirements. ([#1366])
15+
- `subscriptions::*` functions now require `Clone` bound on the context type for ability to have a "fresh" context value each time a new [GraphQL] operation is started in a [WebSocket] connection. ([#1369])
16+
> **COMPATIBILITY**: Previously, it was `Arc`ed inside, sharing the same context value across all [GraphQL] operations of a [WebSocket] connection. To preserve the previous behavior, the `Schema::Context` type should be either wrapped into `Arc` or made `Arc`-based internally.
1517
1618
[#1366]: /../../pull/1366
19+
[#1369]: /../../pull/1369
1720

1821

1922

@@ -87,5 +90,7 @@ See [old CHANGELOG](/../../blob/juniper_actix-v0.4.0/juniper_actix/CHANGELOG.md)
8790
[`juniper_graphql_ws` crate]: https://docs.rs/juniper_graphql_ws
8891
[graphql-transport-ws]: https://github.com/enisdenjo/graphql-ws/blob/v5.14.0/PROTOCOL.md
8992
[graphql-ws]: https://github.com/apollographql/subscriptions-transport-ws/blob/v0.11.0/PROTOCOL.md
93+
[GraphQL]: https://graphql.org
9094
[MSRV]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field
9195
[Semantic Versioning 2.0.0]: https://semver.org
96+
[WebSocket]: https://en.wikipedia.org/wiki/WebSocket

juniper_actix/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ pub mod subscriptions {
207207
Mutation::TypeInfo: Send + Sync,
208208
Subscription: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
209209
Subscription::TypeInfo: Send + Sync,
210-
CtxT: Unpin + Send + Sync + 'static,
210+
CtxT: Clone + Unpin + Send + Sync + 'static,
211211
S: ScalarValue + Send + Sync + 'static,
212212
I: Init<S, CtxT> + Send,
213213
{
@@ -250,7 +250,7 @@ pub mod subscriptions {
250250
Mutation::TypeInfo: Send + Sync,
251251
Subscription: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
252252
Subscription::TypeInfo: Send + Sync,
253-
CtxT: Unpin + Send + Sync + 'static,
253+
CtxT: Clone + Unpin + Send + Sync + 'static,
254254
S: ScalarValue + Send + Sync + 'static,
255255
I: Init<S, CtxT> + Send,
256256
{
@@ -318,7 +318,7 @@ pub mod subscriptions {
318318
Mutation::TypeInfo: Send + Sync,
319319
Subscription: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
320320
Subscription::TypeInfo: Send + Sync,
321-
CtxT: Unpin + Send + Sync + 'static,
321+
CtxT: Clone + Unpin + Send + Sync + 'static,
322322
S: ScalarValue + Send + Sync + 'static,
323323
I: Init<S, CtxT> + Send,
324324
{

juniper_axum/CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ All user visible changes to `juniper_axum` crate will be documented in this file
66

77

88

9+
## master
10+
11+
### BC Breaks
12+
13+
- `subscriptions::*` functions now require `Clone` bound on the context type for ability to have a "fresh" context value each time a new [GraphQL] operation is started in a [WebSocket] connection. ([#1369])
14+
> **COMPATIBILITY**: Previously, it was `Arc`ed inside, sharing the same context value across all [GraphQL] operations of a [WebSocket] connection. To preserve the previous behavior, the `Schema::Context` type should be either wrapped into `Arc` or made `Arc`-based internally.
15+
16+
[#1369]: /../../pull/1369
17+
18+
19+
20+
921
## [0.3.0] · 2025-09-08
1022
[0.3.0]: /../../tree/juniper_axum-v0.3.0/juniper_axum
1123

@@ -90,4 +102,5 @@ All user visible changes to `juniper_axum` crate will be documented in this file
90102
[GraphQL]: http://graphql.org
91103
[GraphQL Playground]: https://github.com/prisma/graphql-playground
92104
[MSRV]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field
93-
[Semantic Versioning 2.0.0]: https://semver.org
105+
[Semantic Versioning 2.0.0]: https://semver.org
106+
[WebSocket]: https://en.wikipedia.org/wiki/WebSocket

juniper_graphql_ws/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@ All user visible changes to `juniper_graphql_ws` crate will be documented in thi
88

99
## master
1010

11+
### BC Breaks
12+
13+
- `Schema::Context` now requires `Clone` bound for ability to have a "fresh" context value each time a new [GraphQL] operation is started in a [WebSocket] connection. ([#1369])
14+
> **COMPATIBILITY**: Previously, it was `Arc`ed inside, sharing the same context value across all [GraphQL] operations of a [WebSocket] connection. To preserve the previous behavior, the `Schema::Context` type should be either wrapped into `Arc` or made `Arc`-based internally.
15+
1116
### Fixed
1217

1318
- Inability to re-subscribe with the same operation `id` after subscription was completed by server. ([#1368])
1419

1520
[#1368]: /../../pull/1368
21+
[#1369]: /../../pull/1369
1622

1723

1824

@@ -70,5 +76,7 @@ See [old CHANGELOG](/../../blob/juniper_graphql_ws-v0.3.0/juniper_graphql_ws/CHA
7076
[`graphql-ws` npm package]: https://npmjs.com/package/graphql-ws
7177
[`juniper` crate]: https://docs.rs/juniper
7278
[`juniper_subscriptions` crate]: https://docs.rs/juniper_subscriptions
79+
[GraphQL]: https://graphql.org
7380
[MSRV]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field
7481
[Semantic Versioning 2.0.0]: https://semver.org
82+
[WebSocket]: https://en.wikipedia.org/wiki/WebSocket

juniper_graphql_ws/src/graphql_transport_ws/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub use self::{
3939

4040
struct ExecutionParams<S: Schema> {
4141
subscribe_payload: SubscribePayload<S::ScalarValue>,
42-
config: Arc<ConnectionConfig<S::Context>>,
42+
config: ConnectionConfig<S::Context>,
4343
schema: S,
4444
}
4545

@@ -81,7 +81,7 @@ enum ConnectionState<S: Schema, I: Init<S::ScalarValue, S::Context>> {
8181
PreInit { init: I, schema: S },
8282
/// Active is the state after a ConnectionInit message has been accepted.
8383
Active {
84-
config: Arc<ConnectionConfig<S::Context>>,
84+
config: ConnectionConfig<S::Context>,
8585
stoppers: HashMap<String, oneshot::Sender<()>>,
8686
schema: S,
8787
},
@@ -121,7 +121,7 @@ impl<S: Schema, I: Init<S::ScalarValue, S::Context>> ConnectionState<S, I> {
121121

122122
(
123123
Self::Active {
124-
config: Arc::new(config),
124+
config,
125125
stoppers: HashMap::new(),
126126
schema,
127127
},
@@ -484,8 +484,7 @@ where
484484

485485
impl<S, I, T> Sink<T> for Connection<S, I>
486486
where
487-
T: TryInto<Input<S::ScalarValue>>,
488-
T::Error: Error,
487+
T: TryInto<Input<S::ScalarValue>, Error: Error>,
489488
S: Schema,
490489
I: Init<S::ScalarValue, S::Context> + Send,
491490
{
@@ -605,6 +604,7 @@ mod test {
605604

606605
use super::{Connection, ConnectionConfig, NextPayload, Output, SubscribePayload};
607606

607+
#[derive(Clone, Copy)]
608608
struct Context(i32);
609609

610610
impl juniper::Context for Context {}

juniper_graphql_ws/src/graphql_ws/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub use self::{
4040

4141
struct ExecutionParams<S: Schema> {
4242
start_payload: StartPayload<S::ScalarValue>,
43-
config: Arc<ConnectionConfig<S::Context>>,
43+
config: ConnectionConfig<S::Context>,
4444
schema: S,
4545
}
4646

@@ -61,7 +61,7 @@ enum ConnectionState<S: Schema, I: Init<S::ScalarValue, S::Context>> {
6161
PreInit { init: I, schema: S },
6262
/// Active is the state after a ConnectionInit message has been accepted.
6363
Active {
64-
config: Arc<ConnectionConfig<S::Context>>,
64+
config: ConnectionConfig<S::Context>,
6565
stoppers: HashMap<String, oneshot::Sender<()>>,
6666
schema: S,
6767
},
@@ -112,7 +112,7 @@ impl<S: Schema, I: Init<S::ScalarValue, S::Context>> ConnectionState<S, I> {
112112

113113
(
114114
Self::Active {
115-
config: Arc::new(config),
115+
config,
116116
stoppers: HashMap::new(),
117117
schema,
118118
},
@@ -430,8 +430,7 @@ where
430430

431431
impl<S, I, T> Sink<T> for Connection<S, I>
432432
where
433-
T: TryInto<ClientMessage<S::ScalarValue>>,
434-
T::Error: Error,
433+
T: TryInto<ClientMessage<S::ScalarValue>, Error: Error>,
435434
S: Schema,
436435
I: Init<S::ScalarValue, S::Context> + Send,
437436
{
@@ -546,6 +545,7 @@ mod test {
546545

547546
use super::{Connection, ConnectionConfig, ConnectionErrorPayload, DataPayload, StartPayload};
548547

548+
#[derive(Clone, Copy)]
549549
struct Context(i32);
550550

551551
impl juniper::Context for Context {}

juniper_graphql_ws/src/schema.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,15 @@ use juniper::{GraphQLSubscriptionType, GraphQLTypeAsync, RootNode, ScalarValue};
55
/// Schema defines the requirements for schemas that can be used for operations. Typically this is
66
/// just an `Arc<RootNode<...>>` and you should not have to implement it yourself.
77
pub trait Schema: Unpin + Clone + Send + Sync + 'static {
8-
/// The context type.
9-
type Context: Unpin + Send + Sync;
8+
/// The context type associates with this [`Schema`].
9+
///
10+
/// # Cloning
11+
///
12+
/// [`Clone`] is required, because the context type is [`Clone`]d each time a new operation is
13+
/// started over a connection. To share the same context value among all the connection's
14+
/// operations, the context type should be either wrapped into an [`Arc`] or implement
15+
/// [`Arc`]-based [`Clone`]ing by itself.
16+
type Context: Clone + Unpin + Send + Sync;
1017

1118
/// The scalar value type.
1219
type ScalarValue: ScalarValue + Send + Sync;
@@ -88,7 +95,7 @@ where
8895
MutationT::TypeInfo: Send + Sync,
8996
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
9097
SubscriptionT::TypeInfo: Send + Sync,
91-
CtxT: Unpin + Send + Sync + 'static,
98+
CtxT: Clone + Unpin + Send + Sync + 'static,
9299
S: ScalarValue + Send + Sync + 'static,
93100
{
94101
type Context = CtxT;
@@ -114,7 +121,7 @@ where
114121
MutationT::TypeInfo: Send + Sync,
115122
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
116123
SubscriptionT::TypeInfo: Send + Sync,
117-
CtxT: Unpin + Send + Sync,
124+
CtxT: Clone + Unpin + Send + Sync,
118125
S: ScalarValue + Send + Sync + 'static,
119126
{
120127
type Context = CtxT;

juniper_warp/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ All user visible changes to `juniper_warp` crate will be documented in this file
66

77

88

9+
## master
10+
11+
### BC Breaks
12+
13+
- `subscriptions::*` functions now require `Clone` bound on the context type for ability to have a "fresh" context value each time a new [GraphQL] operation is started in a [WebSocket] connection. ([#1369])
14+
> **COMPATIBILITY**: Previously, it was `Arc`ed inside, sharing the same context value across all [GraphQL] operations of a [WebSocket] connection. To preserve the previous behavior, the `Schema::Context` type should be either wrapped into `Arc` or made `Arc`-based internally.
15+
16+
[#1369]: /../../pull/1369
17+
18+
19+
20+
921
## [0.9.0] · 2025-09-08
1022
[0.9.0]: /../../tree/juniper_warp-v0.9.0/juniper_warp
1123

@@ -67,5 +79,7 @@ See [old CHANGELOG](/../../blob/juniper_warp-v0.7.0/juniper_warp/CHANGELOG.md).
6779
[`warp` crate]: https://docs.rs/warp
6880
[graphql-transport-ws]: https://github.com/enisdenjo/graphql-ws/blob/v5.14.0/PROTOCOL.md
6981
[graphql-ws]: https://github.com/apollographql/subscriptions-transport-ws/blob/v0.11.0/PROTOCOL.md
82+
[GraphQL]: http://graphql.org
7083
[MSRV]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field
7184
[Semantic Versioning 2.0.0]: https://semver.org
85+
[WebSocket]: https://en.wikipedia.org/wiki/WebSocket

juniper_warp/src/subscriptions.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ where
173173
Mutation::TypeInfo: Send + Sync,
174174
Subscription: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
175175
Subscription::TypeInfo: Send + Sync,
176-
CtxT: Unpin + Send + Sync + 'static,
176+
CtxT: Clone + Unpin + Send + Sync + 'static,
177177
S: ScalarValue + Send + Sync + 'static,
178178
I: juniper_graphql_ws::Init<S, CtxT> + Clone + Send + Sync,
179179
{
@@ -235,7 +235,7 @@ where
235235
Mutation::TypeInfo: Send + Sync,
236236
Subscription: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
237237
Subscription::TypeInfo: Send + Sync,
238-
CtxT: Unpin + Send + Sync + 'static,
238+
CtxT: Clone + Unpin + Send + Sync + 'static,
239239
S: ScalarValue + Send + Sync + 'static,
240240
I: juniper_graphql_ws::Init<S, CtxT> + Send,
241241
{
@@ -282,7 +282,7 @@ where
282282
Mutation::TypeInfo: Send + Sync,
283283
Subscription: GraphQLSubscriptionType<S, Context = CtxT> + Send + 'static,
284284
Subscription::TypeInfo: Send + Sync,
285-
CtxT: Unpin + Send + Sync + 'static,
285+
CtxT: Clone + Unpin + Send + Sync + 'static,
286286
S: ScalarValue + Send + Sync + 'static,
287287
I: juniper_graphql_ws::Init<S, CtxT> + Send,
288288
{

0 commit comments

Comments
 (0)