Skip to content

Commit 26f8b2f

Browse files
committed
Add a ResolverContext member to SelectionSetParams
1 parent 7028ef9 commit 26f8b2f

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

include/graphqlservice/GraphQLService.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,33 @@ constexpr std::string_view strSubscription { "subscription"sv };
113113

114114
}
115115

116+
// Resolvers may be called in multiple different Operation contexts.
117+
enum class ResolverContext
118+
{
119+
// Resolving a Query operation.
120+
Query,
121+
122+
// Resolving a Mutation operation.
123+
Mutation,
124+
125+
// Adding a Subscription. If you need to prepare to send events for this Subsciption
126+
// (e.g. registering an event sink of your own), this is a chance to do that.
127+
NotifySubscribe,
128+
129+
// Resolving a Subscription event.
130+
Subscription,
131+
132+
// Removing a Subscription. If there are no more Subscriptions registered this is an
133+
// opportunity to release resources which are no longer needed.
134+
NotifyUnsubscribe,
135+
};
136+
116137
// Pass a common bundle of parameters to all of the generated Object::getField accessors in a SelectionSet
117138
struct SelectionSetParams
118139
{
140+
// Context for this selection set.
141+
const ResolverContext resolverContext;
142+
119143
// The lifetime of each of these borrowed references is guaranteed until the future returned
120144
// by the accessor is resolved or destroyed. They are owned by the OperationData shared pointer.
121145
const std::shared_ptr<RequestState>& state;

src/GraphQLService.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,7 @@ class SelectionVisitor
913913
void visitFragmentSpread(const peg::ast_node& fragmentSpread);
914914
void visitInlineFragment(const peg::ast_node& inlineFragment);
915915

916+
const ResolverContext _resolverContext;
916917
const std::shared_ptr<RequestState>& _state;
917918
const response::Value& _operationDirectives;
918919
const field_path _path;
@@ -930,7 +931,8 @@ class SelectionVisitor
930931
SelectionVisitor::SelectionVisitor(const SelectionSetParams& selectionSetParams,
931932
const FragmentMap& fragments, const response::Value& variables,
932933
const TypeNames& typeNames, const ResolverMap& resolvers)
933-
: _state(selectionSetParams.state)
934+
: _resolverContext(selectionSetParams.resolverContext)
935+
, _state(selectionSetParams.state)
934936
, _operationDirectives(selectionSetParams.operationDirectives)
935937
, _path(selectionSetParams.errorPath)
936938
, _launch(selectionSetParams.launch)
@@ -1065,6 +1067,7 @@ void SelectionVisitor::visitField(const peg::ast_node& field)
10651067
path.push({ alias });
10661068

10671069
SelectionSetParams selectionSetParams {
1070+
_resolverContext,
10681071
_state,
10691072
_operationDirectives,
10701073
_fragmentDirectives.top().fragmentDefinitionDirectives,
@@ -1445,21 +1448,25 @@ void FragmentDefinitionVisitor::visit(const peg::ast_node& fragmentDefinition)
14451448
class OperationDefinitionVisitor
14461449
{
14471450
public:
1448-
OperationDefinitionVisitor(std::launch launch, std::shared_ptr<RequestState> state, const TypeMap& operations, response::Value&& variables, FragmentMap&& fragments);
1451+
OperationDefinitionVisitor(ResolverContext resolverContext, std::launch launch, std::shared_ptr<RequestState> state,
1452+
const TypeMap& operations, response::Value&& variables, FragmentMap&& fragments);
14491453

14501454
std::future<response::Value> getValue();
14511455

14521456
void visit(const std::string& operationType, const peg::ast_node& operationDefinition);
14531457

14541458
private:
1459+
const ResolverContext _resolverContext;
14551460
const std::launch _launch;
14561461
std::shared_ptr<OperationData> _params;
14571462
const TypeMap& _operations;
14581463
std::future<response::Value> _result;
14591464
};
14601465

1461-
OperationDefinitionVisitor::OperationDefinitionVisitor(std::launch launch, std::shared_ptr<RequestState> state, const TypeMap& operations, response::Value&& variables, FragmentMap&& fragments)
1462-
: _launch(launch)
1466+
OperationDefinitionVisitor::OperationDefinitionVisitor(ResolverContext resolverContext, std::launch launch, std::shared_ptr<RequestState> state,
1467+
const TypeMap& operations, response::Value&& variables, FragmentMap&& fragments)
1468+
: _resolverContext(resolverContext)
1469+
, _launch(launch)
14631470
, _params(std::make_shared<OperationData>(
14641471
std::move(state),
14651472
std::move(variables),
@@ -1534,11 +1541,12 @@ void OperationDefinitionVisitor::visit(const std::string& operationType, const p
15341541

15351542
// Keep the params alive until the deferred lambda has executed
15361543
_result = std::async(_launch,
1537-
[selectionLaunch = _launch, params = std::move(_params), operation = itr->second](const peg::ast_node& selection)
1544+
[selectionContext = _resolverContext, selectionLaunch = _launch, params = std::move(_params), operation = itr->second](const peg::ast_node& selection)
15381545
{
15391546
// The top level object doesn't come from inside of a fragment, so all of the fragment directives are empty.
15401547
const response::Value emptyFragmentDirectives(response::Type::Map);
15411548
const SelectionSetParams selectionSetParams {
1549+
selectionContext,
15421550
params->state,
15431551
params->directives,
15441552
emptyFragmentDirectives,
@@ -1998,14 +2006,20 @@ std::future<response::Value> Request::resolveValidated(std::launch launch, const
19982006
throw schema_exception { { schema_error{ message.str(), { position.line, position.column } } } };
19992007
}
20002008

2009+
const bool isMutation = (operationDefinition.first == strMutation);
2010+
20012011
// http://spec.graphql.org/June2018/#sec-Normal-and-Serial-Execution
2002-
if (operationDefinition.first == strMutation)
2012+
if (isMutation)
20032013
{
20042014
// Force mutations to perform serial execution
20052015
launch = std::launch::deferred;
20062016
}
20072017

2008-
OperationDefinitionVisitor operationVisitor(launch, state, _operations, std::move(variables), std::move(fragments));
2018+
const auto resolverContext = isMutation
2019+
? ResolverContext::Mutation
2020+
: ResolverContext::Query;
2021+
2022+
OperationDefinitionVisitor operationVisitor(resolverContext, launch, state, _operations, std::move(variables), std::move(fragments));
20092023

20102024
operationVisitor.visit(operationDefinition.first, *operationDefinition.second);
20112025

@@ -2193,6 +2207,7 @@ void Request::deliver(std::launch launch, const SubscriptionName& name, const Su
21932207
std::future<response::Value> result;
21942208
response::Value emptyFragmentDirectives(response::Type::Map);
21952209
const SelectionSetParams selectionSetParams {
2210+
ResolverContext::Subscription,
21962211
registration->data->state,
21972212
registration->data->directives,
21982213
emptyFragmentDirectives,

0 commit comments

Comments
 (0)