-
Notifications
You must be signed in to change notification settings - Fork 73
BREAKING: Converts to Swift Concurrency #166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
24080b6
d112be0
9ec313a
9b4a6f2
1bc642c
d25254b
631650a
34268d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,8 +45,7 @@ Once a schema has been defined queries may be executed against it using the glob | |
```swift | ||
let result = try await graphql( | ||
schema: schema, | ||
request: "{ hello }", | ||
eventLoopGroup: eventLoopGroup | ||
request: "{ hello }" | ||
) | ||
``` | ||
|
||
|
@@ -58,33 +57,29 @@ The result of this query is a `GraphQLResult` that encodes to the following JSON | |
|
||
### Subscription | ||
|
||
This package supports GraphQL subscription, but until the integration of `AsyncSequence` in Swift 5.5 the standard Swift library did not | ||
provide an event-stream construct. For historical reasons and backwards compatibility, this library implements subscriptions using an | ||
`EventStream` protocol that nearly every asynchronous stream implementation can conform to. | ||
|
||
To create a subscription field in a GraphQL schema, use the `subscribe` resolver that returns an `EventStream`. You must also provide a | ||
`resolver`, which defines how to process each event as it occurs and must return the field result type. Here is an example: | ||
This package supports GraphQL subscription. To create a subscription field in a GraphQL schema, use the `subscribe` | ||
resolver that returns any type that conforms to `AsyncSequence`. You must also provide a `resolver`, which defines how | ||
to process each event as it occurs and must return the field result type. Here is an example: | ||
|
||
```swift | ||
let schema = try GraphQLSchema( | ||
subscribe: GraphQLObjectType( | ||
name: "Subscribe", | ||
fields: [ | ||
"hello": GraphQLField( | ||
"hello": GraphQLField( | ||
type: GraphQLString, | ||
resolve: { eventResult, _, _, _, _ in // Defines how to transform each event when it occurs | ||
resolve: { eventResult, _, _, _ in // Defines how to transform each event when it occurs | ||
return eventResult | ||
}, | ||
subscribe: { _, _, _, _, _ in // Defines how to construct the event stream | ||
let asyncStream = AsyncThrowingStream<String, Error> { continuation in | ||
subscribe: { _, _, _, _ in // Defines how to construct the event stream | ||
return AsyncThrowingStream<String, Error> { continuation in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that we only support There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great question! No, this just happens to be the example - within the subscription resolver, we support There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool! I spent some time looking for that and couldn’t find it, haha. That was my main concern. Please update the README example making that point clear. Other than that, I’m happy with the PR. 🙂 Actually.. I have a follow up question, haha. Why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Good idea. I've done that in this commit
This is because |
||
let timer = Timer.scheduledTimer( | ||
withTimeInterval: 3, | ||
repeats: true, | ||
) { | ||
continuation.yield("world") // Emits "world" every 3 seconds | ||
continuation.yield("world") // Emits "world" every 3 seconds | ||
} | ||
} | ||
return ConcurrentEventStream<String>(asyncStream) | ||
} | ||
) | ||
] | ||
|
@@ -98,9 +93,8 @@ To execute a subscription use the `graphqlSubscribe` function: | |
let subscriptionResult = try await graphqlSubscribe( | ||
schema: schema, | ||
) | ||
// Must downcast from EventStream to concrete type to use in 'for await' loop below | ||
let concurrentStream = subscriptionResult.stream! as! ConcurrentEventStream | ||
for try await result in concurrentStream.stream { | ||
let stream = subscriptionResult.get() | ||
for try await result in stream { | ||
print(result) | ||
} | ||
``` | ||
|
@@ -111,18 +105,15 @@ The code above will print the following JSON every 3 seconds: | |
{ "hello": "world" } | ||
``` | ||
|
||
The example above assumes that your environment has access to Swift Concurrency. If that is not the case, try using | ||
[GraphQLRxSwift](https://github.com/GraphQLSwift/GraphQLRxSwift) | ||
|
||
## Encoding Results | ||
|
||
If you encode a `GraphQLResult` with an ordinary `JSONEncoder`, there are no guarantees that the field order will match the query, | ||
If you encode a `GraphQLResult` with an ordinary `JSONEncoder`, there are no guarantees that the field order will match the query, | ||
violating the [GraphQL spec](https://spec.graphql.org/June2018/#sec-Serialized-Map-Ordering). To preserve this order, `GraphQLResult` | ||
should be encoded using the `GraphQLJSONEncoder` provided by this package. | ||
|
||
## Support | ||
|
||
This package supports Swift versions in [alignment with Swift NIO](https://github.com/apple/swift-nio?tab=readme-ov-file#swift-versions). | ||
This package aims to support the previous three Swift versions. | ||
|
||
For details on upgrading to new major versions, see [MIGRATION](MIGRATION.md). | ||
|
||
|
@@ -140,7 +131,7 @@ To format your code, install `swiftformat` and run: | |
|
||
```bash | ||
swiftformat . | ||
``` | ||
``` | ||
|
||
Most of this repo mirrors the structure of | ||
(the canonical GraphQL implementation written in Javascript/Typescript)[https://github.com/graphql/graphql-js]. If there is any feature | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe enable strict concurrency as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NeedleInAJayStack have you tried enabling strict concurrency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has a quick look at this. The fact that you throw
Any
around a lot is going to make it very difficult to enable strict concurrency