@@ -3,22 +3,16 @@ import OrderedCollections
33/**
44 * Implements the "Subscribe" algorithm described in the GraphQL specification.
55 *
6-  * Returns a future which resolves to a SubscriptionResult containing either
7-  * a SubscriptionObservable (if successful), or GraphQLErrors (error).
6+  * Returns a `Result` that either succeeds with an `AsyncThrowingStream`, or fails with `GraphQLErrors`.
87 *
98 * If the client-provided arguments to this function do not result in a
10-  * compliant subscription, the future will resolve to a
11-  * SubscriptionResult containing `errors` and no `observable`.
9+  * compliant subscription, the `Result` will fails with descriptive errors.
1210 *
1311 * If the source stream could not be created due to faulty subscription
14-  * resolver logic or underlying systems, the future will resolve to a
15-  * SubscriptionResult containing `errors` and no `observable`.
12+  * resolver logic or underlying systems, the `Result` will fail with errors.
1613 *
17-  * If the operation succeeded, the future will resolve to a SubscriptionResult,
18-  * containing an `observable` which yields a stream of GraphQLResults
14+  * If the operation succeeded, the `Result` will succeed with an `AsyncThrowingStream` of `GraphQLResult`s
1915 * representing the response stream.
20-  *
21-  * Accepts either an object with named arguments, or individual arguments.
2216 */
2317func  subscribe( 
2418    queryStrategy:  QueryFieldExecutionStrategy , 
@@ -30,7 +24,7 @@ func subscribe(
3024    context:  Any , 
3125    variableValues:  [ String :  Map ]  =  [ : ] , 
3226    operationName:  String ? =  nil 
33- )  async  throws  ->  SubscriptionResult  { 
27+ )  async  throws  ->  Result < AsyncThrowingStream < GraphQLResult ,   Error > ,   GraphQLErrors >  { 
3428    let  sourceResult  =  try await  createSourceEventStream ( 
3529        queryStrategy:  queryStrategy, 
3630        mutationStrategy:  mutationStrategy, 
@@ -43,7 +37,7 @@ func subscribe(
4337        operationName:  operationName
4438    ) 
4539
46-     if   let  sourceStream  =   sourceResult. stream  { 
40+     return   sourceResult. map   {  sourceStream  in 
4741        // We must create a new AsyncSequence because AsyncSequence.map requires a concrete type
4842        // (which we cannot know),
4943        // and we need the result to be a concrete type.
@@ -80,30 +74,24 @@ func subscribe(
8074                task. cancel ( ) 
8175            } 
8276        } 
83-         return  SubscriptionResult ( stream:  subscriptionStream,  errors:  sourceResult. errors) 
84-     }  else  { 
85-         return  SubscriptionResult ( errors:  sourceResult. errors) 
77+         return  subscriptionStream
8678    } 
8779} 
8880
8981/**
9082 * Implements the "CreateSourceEventStream" algorithm described in the
9183 * GraphQL specification, resolving the subscription source event stream.
9284 *
93-  * Returns a Future which resolves to a SourceEventStreamResult, containing
94-  * either an Observable (if successful) or GraphQLErrors (error).
85+  * Returns a Result that either succeeds with an `AsyncSequence` or fails with `GraphQLErrors`.
9586 *
9687 * If the client-provided arguments to this function do not result in a
97-  * compliant subscription, the future will resolve to a
98-  * SourceEventStreamResult containing `errors` and no `observable`.
88+  * compliant subscription, the `Result` will fail with descriptive errors.
9989 *
10090 * If the source stream could not be created due to faulty subscription
101-  * resolver logic or underlying systems, the future will resolve to a
102-  * SourceEventStreamResult containing `errors` and no `observable`.
91+  * resolver logic or underlying systems, the `Result` will fail with errors.
10392 *
104-  * If the operation succeeded, the future will resolve to a SubscriptionResult,
105-  * containing an `observable` which yields a stream of event objects
106-  * returned by the subscription resolver.
93+  * If the operation succeeded, the `Result` will succeed with an AsyncSequence for the
94+  * event stream returned by the resolver.
10795 *
10896 * A Source Event Stream represents a sequence of events, each of which triggers
10997 * a GraphQL execution for that event.
@@ -123,32 +111,37 @@ func createSourceEventStream(
123111    context:  Any , 
124112    variableValues:  [ String :  Map ]  =  [ : ] , 
125113    operationName:  String ? =  nil 
126- )  async  throws  ->  SourceEventStreamResult  { 
114+ )  async  throws  ->  Result < any  AsyncSequence ,  GraphQLErrors >  { 
115+     // If a valid context cannot be created due to incorrect arguments,
116+     // this will throw an error.
117+     let  exeContext  =  try buildExecutionContext ( 
118+         queryStrategy:  queryStrategy, 
119+         mutationStrategy:  mutationStrategy, 
120+         subscriptionStrategy:  subscriptionStrategy, 
121+         schema:  schema, 
122+         documentAST:  documentAST, 
123+         rootValue:  rootValue, 
124+         context:  context, 
125+         rawVariableValues:  variableValues, 
126+         operationName:  operationName
127+     ) 
127128    do  { 
128-         // If a valid context cannot be created due to incorrect arguments,
129-         // this will throw an error.
130-         let  exeContext  =  try buildExecutionContext ( 
131-             queryStrategy:  queryStrategy, 
132-             mutationStrategy:  mutationStrategy, 
133-             subscriptionStrategy:  subscriptionStrategy, 
134-             schema:  schema, 
135-             documentAST:  documentAST, 
136-             rootValue:  rootValue, 
137-             context:  context, 
138-             rawVariableValues:  variableValues, 
139-             operationName:  operationName
140-         ) 
141129        return  try await  executeSubscription ( context:  exeContext) 
142130    }  catch  let  errorGraphQLError  { 
143-         return  SourceEventStreamResult ( errors:  [ error] ) 
131+         // If it is a GraphQLError, report it as a failure.
132+         return  . failure( . init( [ error] ) ) 
133+     }  catch  let  errorsGraphQLErrors  { 
134+         // If it is a GraphQLErrors, report it as a failure.
135+         return  . failure( errors) 
144136    }  catch  { 
145-         return  SourceEventStreamResult ( errors:  [ GraphQLError ( error) ] ) 
137+         // Otherwise treat the error as a system-class error and re-throw it.
138+         throw  error
146139    } 
147140} 
148141
149142func  executeSubscription( 
150143    context:  ExecutionContext 
151- )  async  throws  ->  SourceEventStreamResult  { 
144+ )  async  throws  ->  Result < any   AsyncSequence ,   GraphQLErrors >  { 
152145    // Get the first node
153146    let  type  =  try getOperationRootType ( schema:  context. schema,  operation:  context. operation) 
154147    var  inputFields :  OrderedDictionary < String ,  [ Field ] >  =  [ : ] 
@@ -238,35 +231,21 @@ func executeSubscription(
238231        resolved =  success
239232    } 
240233    if  !context. errors. isEmpty { 
241-         return  SourceEventStreamResult ( errors :   context. errors) 
234+         return  . failure ( . init ( context. errors) ) 
242235    }  else  if  let  error =  resolved as?  GraphQLError  { 
243-         return  SourceEventStreamResult ( errors :   [ error] ) 
236+         return  . failure ( . init ( [ error] ) ) 
244237    }  else  if  let  stream =  resolved as?  any  AsyncSequence  { 
245-         return  SourceEventStreamResult ( stream :   stream) 
238+         return  . success ( stream) 
246239    }  else  if  resolved ==  nil  { 
247-         return  SourceEventStreamResult ( errors :   [ 
240+         return  . failure ( . init ( [ 
248241            GraphQLError ( message:  " Resolved subscription was nil " ) , 
249-         ] ) 
242+         ] ) ) 
250243    }  else  { 
251244        let  resolvedObj  =  resolved as  AnyObject 
252-         return  SourceEventStreamResult ( errors :   [ 
245+         return  . failure ( . init ( [ 
253246            GraphQLError ( 
254247                message:  " Subscription field resolver must return an AsyncSequence. Received: ' \( resolvedObj) ' " 
255248            ) , 
256-         ] ) 
257-     } 
258- } 
259- 
260- // Subscription resolvers MUST return observables that are declared as 'Any' due to Swift not having
261- // covariant generic support for type
262- // checking. Normal resolvers for subscription fields should handle type casting, same as resolvers
263- // for query fields.
264- struct  SourceEventStreamResult  { 
265-     public  let  stream :  ( any  AsyncSequence ) ? 
266-     public  let  errors :  [ GraphQLError ] 
267- 
268-     public  init ( stream:  ( any  AsyncSequence ) ? =  nil ,  errors:  [ GraphQLError ]  =  [ ] )  { 
269-         self . stream =  stream
270-         self . errors =  errors
249+         ] ) ) 
271250    } 
272251} 
0 commit comments