Skip to content

Commit 8d1917b

Browse files
committed
Write fieldparams.md content
1 parent feb16c3 commit 8d1917b

File tree

2 files changed

+89
-2
lines changed

2 files changed

+89
-2
lines changed

doc/fieldparams.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Common Field Parameters
2+
3+
The `resolveField` methods generated by `schemagen` will unpack any arguments
4+
matching the `schema` from the `query` and pass those to the `getField` method
5+
defined by the implementer. However, the implementer might need to inspect
6+
shared state or `directives` from the `query`, so the `resolveField` method
7+
also packs that information into a `graphql::service::FieldParams` struct and
8+
passes it to every `getField` method as the first parameter.
9+
10+
## Details of Field Parameters
11+
12+
The `graphql::service::FieldParams` struct is declared in [GraphQLService.h](../include/graphqlservice/GraphQLService.h):
13+
```cpp
14+
// Pass a common bundle of parameters to all of the generated Object::getField accessors in a SelectionSet
15+
struct SelectionSetParams
16+
{
17+
// The lifetime of each of these borrowed references is guaranteed until the future returned
18+
// by the accessor is resolved or destroyed. They are owned by the OperationData shared pointer.
19+
const std::shared_ptr<RequestState>& state;
20+
const response::Value& operationDirectives;
21+
const response::Value& fragmentDefinitionDirectives;
22+
23+
// Fragment directives are shared for all fields in that fragment, but they aren't kept alive
24+
// after the call to the last accessor in the fragment. If you need to keep them alive longer,
25+
// you'll need to explicitly copy them into other instances of response::Value.
26+
const response::Value& fragmentSpreadDirectives;
27+
const response::Value& inlineFragmentDirectives;
28+
};
29+
30+
// Pass a common bundle of parameters to all of the generated Object::getField accessors.
31+
struct FieldParams : SelectionSetParams
32+
{
33+
explicit FieldParams(const SelectionSetParams& selectionSetParams, response::Value&& directives);
34+
35+
// Each field owns its own field-specific directives. Once the accessor returns it will be destroyed,
36+
// but you can move it into another instance of response::Value to keep it alive longer.
37+
response::Value fieldDirectives;
38+
};
39+
```
40+
41+
### Request State
42+
43+
The `SelectionSetParams::state` member is a reference to the
44+
`std::shared_ptr<graphql::service::RequestState>` parameter passed to
45+
`Request::resolve` (see [resolvers.md](./resolvers.md) for more info):
46+
```cpp
47+
// The RequestState is nullable, but if you have multiple threads processing requests and there's any
48+
// per-request state that you want to maintain throughout the request (e.g. optimizing or batching
49+
// backend requests), you can inherit from RequestState and pass it to Request::resolve to correlate the
50+
// asynchronous/recursive callbacks and accumulate state in it.
51+
struct RequestState : std::enable_shared_from_this<RequestState>
52+
{
53+
};
54+
```
55+
56+
### Scoped Directives
57+
58+
Each of the `directives` members contains the values of the `directives` and
59+
any of their arguments which were in effect at that scope of the `query`.
60+
Implementers may inspect those values in the call to `getField` and alter their
61+
behavior based on those custom `directives`.
62+
63+
As noted in the comments, the `fragmentSpreadDirectives` and
64+
`inlineFragmentDirectives` are borrowed `const` references, shared accross
65+
calls to multiple `getField` methods, but they will not be kept alive after
66+
the relevant `SelectionSet` has been resolved. The `fieldDirectives` member is
67+
passed by value and is not shared with other `getField` method calls, but it
68+
will not be kept alive after that call returns. It's up to the implementer to
69+
capture the values in these `directives` which they might need for asynchronous
70+
evaulation after the call to the current `getField` method has returned.
71+
72+
The implementer does not need to capture the values of `operationDirectives`
73+
or `fragmentDefinitionDirectives` because those are kept alive until the
74+
`operation` and all of its `std::future` results are resolved. Although they
75+
passed by `const` reference, the reference should always be valid as long as
76+
there's a pending result from the `getField` call.
77+
78+
## Related Documents
79+
80+
1. The `getField` methods are discussed in more detail in [resolvers.md](./resolvers.md).
81+
2. Built-in and custom `directives` are discussed in [directives.md](./directives.md).

doc/resolvers.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ In this example, the `resolveId` method invokes `getId`:
7373
virtual service::FieldResult<response::IdType> getId(service::FieldParams&& params) const override;
7474
```
7575

76-
There are also a couple of interesting quirks in this example:
76+
There are a couple of interesting quirks in this example:
7777
1. The `Appointment object` implements and inherits from the `Node interface`,
7878
which already declared `getId` as a pure-virtual method. That's what the
7979
`override` keyword refers to.
@@ -87,4 +87,10 @@ will throw a `std::runtime_error`, which the `resolver` converts into an entry
8787
in the `response errors` collection:
8888
```cpp
8989
throw std::runtime_error(R"ex(Appointment::getId is not implemented)ex");
90-
```
90+
```
91+
92+
Although the `id field` does not take any arguments according to the sample
93+
[schema](../samples/today/schema.today.graphql), this example also shows how
94+
every `getField` method takes a `graphql::service::FieldParams` struct as
95+
its first parameter. There are more details on this in the [fieldparams.md](./fieldparams.md)
96+
document.

0 commit comments

Comments
 (0)