Skip to content

Commit aee8841

Browse files
author
Jay Herron
committed
Adds handling for multiple errors
1 parent 7adab89 commit aee8841

File tree

2 files changed

+57
-39
lines changed

2 files changed

+57
-39
lines changed

Sources/GraphQL/Subscription/Subscribe.swift

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,9 @@ func subscribe(
5353
operationName: operationName
5454
)
5555

56-
return sourceFuture.map{ subscriptionResult -> SubscriptionResult in
57-
do {
58-
let subscriptionObserver = try subscriptionResult.get()
59-
let eventObserver = subscriptionObserver.map { eventPayload -> Future<GraphQLResult> in
56+
return sourceFuture.map{ sourceResult -> SubscriptionResult in
57+
if let sourceObservable = sourceResult.observable {
58+
let subscriptionObservable = sourceObservable.map { eventPayload -> Future<GraphQLResult> in
6059

6160
// For each payload yielded from a subscription, map it over the normal
6261
// GraphQL `execute` function, with `payload` as the rootValue.
@@ -78,11 +77,9 @@ func subscribe(
7877
operationName: operationName
7978
)
8079
}
81-
return SubscriptionResult.success(eventObserver)
82-
} catch let graphQLError as GraphQLError {
83-
return SubscriptionResult.failure(graphQLError)
84-
} catch let error {
85-
return SubscriptionResult.failure(GraphQLError(error))
80+
return SubscriptionResult(observable: subscriptionObservable)
81+
} else {
82+
return SubscriptionResult(errors: sourceResult.errors)
8683
}
8784
}
8885
}
@@ -164,9 +161,9 @@ func createSourceEventStream(
164161
result: nil
165162
)
166163

167-
return eventLoopGroup.next().makeSucceededFuture(SourceEventStreamResult.failure(error))
164+
return eventLoopGroup.next().makeSucceededFuture(SourceEventStreamResult(errors: [error]))
168165
} catch {
169-
return eventLoopGroup.next().makeSucceededFuture(SourceEventStreamResult.failure(GraphQLError(error)))
166+
return eventLoopGroup.next().makeSucceededFuture(SourceEventStreamResult(errors: [GraphQLError(error)]))
170167
}
171168
}
172169

@@ -192,7 +189,7 @@ func executeSubscription(
192189
let fieldNode = fieldNodes.first!
193190

194191
guard let fieldDef = getFieldDef(schema: context.schema, parentType: type, fieldAST: fieldNode) else {
195-
throw GraphQLError.init(
192+
throw GraphQLError(
196193
message: "`The subscription field '\(fieldNode.name.value)' is not defined.`",
197194
nodes: fieldNodes
198195
)
@@ -237,34 +234,56 @@ func executeSubscription(
237234
let resolvedFuture:Future<Any?>
238235
switch resolvedFutureOrError {
239236
case let .failure(error):
240-
throw error
237+
if let graphQLError = error as? GraphQLError {
238+
throw graphQLError
239+
} else {
240+
throw GraphQLError(error)
241+
}
241242
case let .success(success):
242243
resolvedFuture = success
243244
}
244245
return resolvedFuture.map { resolved -> SourceEventStreamResult in
245246
if !context.errors.isEmpty {
246-
// TODO improve this to return multiple errors if we have them.
247-
return SourceEventStreamResult.failure(context.errors.first!)
247+
return SourceEventStreamResult(errors: context.errors)
248248
} else if let error = resolved as? GraphQLError {
249-
return SourceEventStreamResult.failure(error)
249+
return SourceEventStreamResult(errors: [error])
250250
} else if let observable = resolved as? SourceEventStreamObservable {
251-
return SourceEventStreamResult.success(observable)
251+
return SourceEventStreamResult(observable: observable)
252252
} else if resolved == nil {
253-
return SourceEventStreamResult.failure(
253+
return SourceEventStreamResult(errors: [
254254
GraphQLError(message: "Resolved subscription was nil")
255-
)
255+
])
256256
} else {
257257
let resolvedObj = resolved as AnyObject
258-
return SourceEventStreamResult.failure(
258+
return SourceEventStreamResult(errors: [
259259
GraphQLError(
260260
message: "Subscription field resolver must return SourceEventStreamObservable. Received: '\(resolvedObj)'"
261261
)
262-
)
262+
])
263263
}
264264
}
265265
}
266266

267-
typealias SubscriptionObservable = Observable<Future<GraphQLResult>>
268-
typealias SubscriptionResult = Result<SubscriptionObservable, GraphQLError>
267+
public struct SubscriptionResult {
268+
public var observable: SubscriptionObservable?
269+
public var errors: [GraphQLError]
270+
271+
public init(observable: SubscriptionObservable? = nil, errors: [GraphQLError] = []) {
272+
self.observable = observable
273+
self.errors = errors
274+
}
275+
}
276+
public typealias SubscriptionObservable = Observable<Future<GraphQLResult>>
277+
278+
struct SourceEventStreamResult {
279+
public var observable: SourceEventStreamObservable?
280+
public var errors: [GraphQLError]
281+
282+
public init(observable: SourceEventStreamObservable? = nil, errors: [GraphQLError] = []) {
283+
self.observable = observable
284+
self.errors = errors
285+
}
286+
}
269287
typealias SourceEventStreamObservable = Observable<Any>
270-
typealias SourceEventStreamResult = Result<SourceEventStreamObservable, GraphQLError>
288+
289+

Tests/GraphQLTests/Subscription/SubscriptionTests.swift

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@ class SubscriptionTests : XCTestCase {
172172
"""
173173
)
174174
) { error in
175-
let graphQlError = error as! GraphQLError
176-
XCTAssertEqual(graphQlError.message, "`The subscription field 'unknownField' is not defined.`")
177-
XCTAssertEqual(graphQlError.locations, [SourceLocation(line: 2, column: 5)])
175+
let graphQLError = error as! GraphQLError
176+
XCTAssertEqual(graphQLError.message, "`The subscription field 'unknownField' is not defined.`")
177+
XCTAssertEqual(graphQLError.locations, [SourceLocation(line: 2, column: 5)])
178178
}
179179
}
180180

@@ -203,9 +203,9 @@ class SubscriptionTests : XCTestCase {
203203
}
204204
""")
205205
) { error in
206-
let graphQlError = error as! GraphQLError
206+
let graphQLError = error as! GraphQLError
207207
XCTAssertEqual(
208-
graphQlError.message,
208+
graphQLError.message,
209209
"Subscription field resolver must return SourceEventStreamObservable. Received: 'test'"
210210
)
211211
}
@@ -221,8 +221,8 @@ class SubscriptionTests : XCTestCase {
221221
}
222222
""")
223223
) { error in
224-
let graphQlError = error as! GraphQLError
225-
XCTAssertEqual(graphQlError.message, "test error")
224+
let graphQLError = error as! GraphQLError
225+
XCTAssertEqual(graphQLError.message, "test error")
226226
}
227227
}
228228

@@ -278,9 +278,9 @@ class SubscriptionTests : XCTestCase {
278278
]
279279
)
280280
) { error in
281-
let graphQlError = error as! GraphQLError
281+
let graphQLError = error as! GraphQLError
282282
XCTAssertEqual(
283-
graphQlError.message,
283+
graphQLError.message,
284284
"Variable \"$priority\" got invalid value \"meow\".\nExpected type \"Int\", found \"meow\"."
285285
)
286286
}
@@ -752,7 +752,7 @@ private func createSubscription(
752752
variableValues: [String: Map] = [:]
753753
) throws -> SubscriptionObservable {
754754
let document = try parse(source: query)
755-
let subscriptionOrError = try subscribe(
755+
let result = try subscribe(
756756
queryStrategy: SerialFieldExecutionStrategy(),
757757
mutationStrategy: SerialFieldExecutionStrategy(),
758758
subscriptionStrategy: SerialFieldExecutionStrategy(),
@@ -766,10 +766,9 @@ private func createSubscription(
766766
operationName: nil
767767
).wait()
768768

769-
switch subscriptionOrError {
770-
case .success(let subscription):
771-
return subscription
772-
case .failure(let error):
773-
throw error
769+
if let observable = result.observable {
770+
return observable
771+
} else {
772+
throw result.errors.first! // We may have more than one...
774773
}
775774
}

0 commit comments

Comments
 (0)