Skip to content

Commit 70dd480

Browse files
committed
Write subscriptions content
1 parent 64aee4b commit 70dd480

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

doc/subscriptions.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Subscriptions
2+
3+
Subscriptions in GraphQL are asynchronous and event driven. Typically you need
4+
to have a callback installed, e.g. over a WebSocket connection, which receives
5+
the response to a subscribed query anytime it is updated. Since this library
6+
is protocol agnostic, it doesn't include the delivery mechanism. But it does
7+
provide a way to register callbacks when adding a subscription, and you can
8+
define trigger conditions when delivering an update to selectively dispatch
9+
the subscriptions to those listeners.
10+
11+
## Adding/Removing a Listener
12+
13+
Subscriptions are created or removed by calling the `Request::subscribe`
14+
and `Request::unsubscribe` methods in [GraphQLService.h](../include/GraphQLService.h):
15+
```cpp
16+
SubscriptionKey subscribe(SubscriptionParams&& params, SubscriptionCallback&& callback);
17+
void unsubscribe(SubscriptionKey key);
18+
```
19+
You need to fill in a `SubscriptionParams` struct with the [parsed](./parsing.md)
20+
query and any other relevant operation parameters:
21+
```cpp
22+
// You can still sub-class RequestState and use that in the state parameter to Request::subscribe
23+
// to add your own state to the service callbacks that you receive while executing the subscription
24+
// query.
25+
struct SubscriptionParams
26+
{
27+
std::shared_ptr<RequestState> state;
28+
peg::ast query;
29+
std::string operationName;
30+
response::Value variables;
31+
};
32+
```
33+
The `SubscriptionCallback` signature is:
34+
```cpp
35+
// Subscription callbacks receive the response::Value representing the result of evaluating the
36+
// SelectionSet against the payload.
37+
using SubscriptionCallback = std::function<void(std::future<response::Value>)>;
38+
```
39+
40+
## Delivering Subscription Updates
41+
42+
There are currently three `Request::deliver` overrides you can choose from when
43+
sending updates to any subscribed listeners. The first one is the simplest,
44+
it will evaluate each subscribed query against the `subscriptionObject`
45+
parameter (which should match the `Subscription` type in the `schema`). It will
46+
unconditionally invoke every subscribed `SubscriptionCallback` callback with
47+
the response to its query:
48+
```cpp
49+
void deliver(const SubscriptionName& name, const std::shared_ptr<Object>& subscriptionObject) const;
50+
```
51+
52+
The second override adds argument filtering. It will look at the field
53+
arguments in the subscription `query`, and if all of the required parameters
54+
in the `arguments` parameter are present and are an exact match it will dispatch the callback to that subscription:
55+
```cpp
56+
void deliver(const SubscriptionName& name, const SubscriptionArguments& arguments, const std::shared_ptr<Object>& subscriptionObject) const;
57+
```
58+
59+
The last override lets you customize the the way that the required arguments
60+
are matched. Instead of an exact match or making all of the arguments required,
61+
it will dispatch the callback if the `apply` function parameter returns true
62+
for every required field in the subscription `query`.
63+
```cpp
64+
void deliver(const SubscriptionName& name, const SubscriptionFilterCallback& apply, const std::shared_ptr<Object>& subscriptionObject) const;
65+
```
66+
67+
## Handling Multiple Operation Types
68+
69+
Some service implementations (e.g. Apollo over HTTP) use a single pipe to
70+
manage subscriptions and resolve queries or mutations. You can't necessarily
71+
tell which operation type it is without parsing the query and searching for
72+
a specific operation name, so it's hard to tell whether you should call
73+
`resolve` or `subscribe` when the request is received that way. To help with
74+
that, there's a public `Request::findOperationDefinition` method which returns
75+
the operation type as a `std::string` along with a pointer to the AST node for
76+
the selected operation in the parsed query:
77+
```cpp
78+
std::pair<std::string, const peg::ast_node*> findOperationDefinition(const peg::ast_node& root, const std::string& operationName) const;
79+
```

0 commit comments

Comments
 (0)