Repository navigation
Commit c0ba6d4
Adopt pending/incremental/completed delivery format (#609)
Adopted the pending/incremental/completed delivery format of incremental delivery v0.2
Incremental delivery over graphql-transport-ws now uses the
pending/incremental/completed/hasNext wire format of the incremental delivery
specification v0.2, the one graphql-js 17 and Apollo Client's
GraphQL17Alpha9Handler consume. Every deferred or streamed field is announced
once in a `pending` entry and identified afterwards by a short id: a deferred
field is announced at the object containing it and delivered as an object map
of that field, a streamed field is announced at its own path and its items are
delivered in list order, batched when the engine produces them together. A
field whose announcement never reached the client is not completed, `errors`
is omitted when there are none, and the final payload reports `hasNext: false`.
Directives and validation:
- `@defer` and `@stream` declare `if: Boolean = true` and `label: String`,
`@stream` also `initialCount: Int = 0`. `@defer` is allowed on fields,
fragment spreads and inline fragments, `@stream` on fields only. `if: false`
executes the field inline (a literal is decided while planning, a variable
at execution), `initialCount` delivers the first items with the initial
payload and streams the rest through the same enumerator, and a stream's
label travels in its announcement.
- New validation rules: `@stream` only on list fields; no `@defer`/`@stream`
in a subscription operation or on a mutation root field unless disabled with
`if: false`; labels are string literals, unique per operation over the
fragments it spreads.
Engine:
- The announcements of nested deferred and streamed fields are carried as
data by a private `AnnouncedEvents` wrapper, so a containing payload replays
them by concatenation instead of capturing them under a lock at subscription
time; `ResolverResult` keeps its signature.
- `ofAsyncEnumerableResolved` delivers results through a single-reader
channel with one emitter, which releases each concurrency slot after
emitting; the `SemaphoreSlim` bounding `maxConcurrency` is the only
synchronization primitive left.
- `DeferredPending` carries `InitialCount`.
Middleware, rewritten around single-owner loops and `System.Threading.Channels`:
- Each connection runs a reader loop (sole reader of the socket), a control
loop (sole owner of the subscription registry) and a sender loop (sole
writer of the socket, including its close), plus one worker per subscription
whose observer only queues events. No lock, no `SemaphoreSlim` gate, no
`.Wait()` and no start-up barrier remain; the connection-init timeout is a
`Task.WhenAny`, and shutdown closes the socket gracefully.
- The former closure nest is split into WebSocketErrors, WebSocketMessaging,
WebSocketTransport, SubscriptionPayloads, SubscriptionWorker and
WebSocketConnection. `GraphQLTransportWS.SubProtocol` names the
sub-protocol once.
Breaking changes:
- `SubscriptionExecutionResult.Data` and `IncrementalResult.Data` are
`Skippable<obj voption>`, `SubscriptionExecutionResult` gains `Pending`,
`Incremental`, `Completed` and `HasNext` and loses `Path`,
`IncrementalResult` gains `SubPath`.
- `GQLDeferredResponseContent.DeferredPending` gains `InitialCount`.
- `@defer`/`@stream` gain the arguments above and drop the
`FRAGMENT_DEFINITION` location.
- `SubscriptionsDict`, `SubscriptionUnsubscriber` and `OnUnsubscribeAction`
are removed from `FSharp.Data.GraphQL.Shared.WebSockets`, together with
`GraphQLSubscriptionsManagement` and the internal
`Observable.withCompletionMarker`.
Tests measure the engine, the translator and the serialization against the
specification (end-to-end payload sequences with protocol invariants, defer
inside stream, error bubbling inside a deferred payload, null parents, root
and mutation defers, `initialCount`, labels, validation rules) and add
real-socket tests of the middleware hosted through `WebApplicationFactory`;
the end-to-end tests tolerate a loaded CI runner. Release notes, the
type-system docs and the project instructions (XML comment rules, primary
constructor documentation) are updated.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: xperiandri <2365592+xperiandri@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>1 parent 54cc2be commit c0ba6d4
44 files changed
Lines changed: 5123 additions & 1386 deletions
File tree
- docs
- src
- FSharp.Data.GraphQL.Server.AspNetCore
- FSharp.Data.GraphQL.Server
- tests
- FSharp.Data.GraphQL.IntegrationTests
- FSharp.Data.GraphQL.Tests
- AspNetCore
- Helpers and Extensions
- Relay
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
288 | 288 | | |
289 | 289 | | |
290 | 290 | | |
291 | | - | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
292 | 295 | | |
293 | 296 | | |
294 | 297 | | |
| |||
301 | 304 | | |
302 | 305 | | |
303 | 306 | | |
304 | | - | |
305 | | - | |
306 | | - | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
307 | 316 | | |
308 | 317 | | |
309 | 318 | | |
310 | 319 | | |
311 | 320 | | |
312 | 321 | | |
313 | | - | |
314 | 322 | | |
315 | 323 | | |
316 | 324 | | |
| 325 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| 101 | + | |
| 102 | + | |
101 | 103 | | |
102 | 104 | | |
103 | 105 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
23 | 29 | | |
24 | 30 | | |
25 | 31 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
64 | 64 | | |
65 | 65 | | |
66 | 66 | | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
67 | 73 | | |
68 | 74 | | |
69 | 75 | | |
70 | 76 | | |
71 | 77 | | |
72 | | - | |
| 78 | + | |
73 | 79 | | |
74 | 80 | | |
75 | 81 | | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
| |||
This file was deleted.
0 commit comments