Closed cshadek closed 2 years ago
Yes, I'm doing it successfully. Here's a really rough example that I haven't tested at all but it shows the main steps:
func routes(_ app: Application, apiBuilder: OpenAPIBuilder) throws {
routes.webSocket(
"graphqlSubscribe",
onUpgrade: { request, websocket in
let api = API()
let context = Context(db: app.db)
let disposeBag = DisposeBag()
websocket.onText { _, message in
let json = message.data(using: .utf8)!
let graphQLRequest = try! JSONDecoder().decode(GraphQLRequest.self, from: json)
api.subscribe(
request: graphQLRequest.query,
context: context,
on: request.eventLoop,
variables: graphQLRequest.variables,
operationName: graphQLRequest.operationName
).map { result in
let streamOpt = result.stream!
let stream = streamOpt as! ObservableSubscriptionEventStream
let observable = stream.observable
observable.subscribe(
onNext: { resultFuture in
resultFuture.whenSuccess { result in
websocket.send(try! JSONEncoder().encode(result))
}
},
onCompleted: { _ in
websocket.close()
}
).disposed(by: disposeBag)
}
}
}
)
}
Basically,
Granted there's a lot more work to do, like conforming to subprotocols, error handling, memory leaks, etc. but this should hopefully get you started.
I ended up using a library called Pioneer that hides away some of the GraphiQL, websocket, and other hosting logic. It also has a bunch of extensions to make Graphiti have async await support and even the subscriptions are asyncstreams too.
Has anyone tried this? I assume we have to use Vapor's websocket API. Is that correct?