|
1 | 1 | package graphql.execution; |
2 | 2 |
|
| 3 | +import graphql.Assert; |
3 | 4 | import graphql.ExecutionResult; |
4 | 5 | import graphql.ExecutionResultImpl; |
5 | 6 | import graphql.GraphQLContext; |
|
15 | 16 | import graphql.language.Field; |
16 | 17 | import graphql.schema.GraphQLFieldDefinition; |
17 | 18 | import graphql.schema.GraphQLObjectType; |
| 19 | +import org.reactivestreams.FlowAdapters; |
18 | 20 | import org.reactivestreams.Publisher; |
19 | 21 |
|
20 | 22 | import java.util.concurrent.CompletableFuture; |
21 | 23 | import java.util.concurrent.CompletionStage; |
| 24 | +import java.util.concurrent.Flow; |
22 | 25 | import java.util.function.Function; |
23 | 26 |
|
24 | | -import static graphql.Assert.assertTrue; |
25 | 27 | import static graphql.execution.instrumentation.SimpleInstrumentationContext.nonNullCtx; |
26 | 28 | import static java.util.Collections.singletonMap; |
27 | 29 |
|
@@ -71,14 +73,12 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont |
71 | 73 | CompletableFuture<ExecutionResult> overallResult = sourceEventStream.thenApply((publisher) -> |
72 | 74 | { |
73 | 75 | if (publisher == null) { |
74 | | - ExecutionResultImpl executionResult = new ExecutionResultImpl(null, executionContext.getErrors()); |
75 | | - return executionResult; |
| 76 | + return new ExecutionResultImpl(null, executionContext.getErrors()); |
76 | 77 | } |
77 | 78 | Function<Object, CompletionStage<ExecutionResult>> mapperFunction = eventPayload -> executeSubscriptionEvent(executionContext, parameters, eventPayload); |
78 | 79 | boolean keepOrdered = keepOrdered(executionContext.getGraphQLContext()); |
79 | 80 | SubscriptionPublisher mapSourceToResponse = new SubscriptionPublisher(publisher, mapperFunction, keepOrdered); |
80 | | - ExecutionResultImpl executionResult = new ExecutionResultImpl(mapSourceToResponse, executionContext.getErrors()); |
81 | | - return executionResult; |
| 81 | + return new ExecutionResultImpl(mapSourceToResponse, executionContext.getErrors()); |
82 | 82 | }); |
83 | 83 |
|
84 | 84 | // dispatched the subscription query |
@@ -112,14 +112,33 @@ private CompletableFuture<Publisher<Object>> createSourceEventStream(ExecutionCo |
112 | 112 | CompletableFuture<FetchedValue> fieldFetched = Async.toCompletableFuture(fetchField(executionContext, newParameters)); |
113 | 113 | return fieldFetched.thenApply(fetchedValue -> { |
114 | 114 | Object publisher = fetchedValue.getFetchedValue(); |
115 | | - if (publisher != null) { |
116 | | - assertTrue(publisher instanceof Publisher, () -> "Your data fetcher must return a Publisher of events when using graphql subscriptions"); |
117 | | - } |
118 | | - //noinspection unchecked,DataFlowIssue |
119 | | - return (Publisher<Object>) publisher; |
| 115 | + return mkReactivePublisher(publisher); |
120 | 116 | }); |
121 | 117 | } |
122 | 118 |
|
| 119 | + /** |
| 120 | + * The user code can return either a reactive stream {@link Publisher} or a JDK {@link Flow.Publisher} |
| 121 | + * and we adapt it to a reactive streams one since we use reactive streams in our implementation. |
| 122 | + * |
| 123 | + * @param publisherObj - the object returned from the data fetcher as the source of events |
| 124 | + * |
| 125 | + * @return a reactive streams {@link Publisher} always |
| 126 | + */ |
| 127 | + @SuppressWarnings("unchecked") |
| 128 | + private static Publisher<Object> mkReactivePublisher(Object publisherObj) { |
| 129 | + if (publisherObj != null) { |
| 130 | + if (publisherObj instanceof Publisher) { |
| 131 | + return (Publisher<Object>) publisherObj; |
| 132 | + } else if (publisherObj instanceof Flow.Publisher) { |
| 133 | + Flow.Publisher<Object> flowPublisher = (Flow.Publisher<Object>) publisherObj; |
| 134 | + return FlowAdapters.toPublisher(flowPublisher); |
| 135 | + } else { |
| 136 | + return Assert.assertShouldNeverHappen("Your data fetcher must return a Publisher of events when using graphql subscriptions"); |
| 137 | + } |
| 138 | + } |
| 139 | + return null; // null is valid - we return null data in this case |
| 140 | + } |
| 141 | + |
123 | 142 | /* |
124 | 143 | ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue): |
125 | 144 |
|
|
0 commit comments