@@ -162,7 +162,7 @@ struct await_worker_thread : coro::suspend_always
162
162
}
163
163
};
164
164
165
- // Type-erased awaitable, if you want finer grain control .
165
+ // Type-erased awaitable.
166
166
class await_async : public coro ::suspend_always
167
167
{
168
168
private:
@@ -172,6 +172,7 @@ class await_async : public coro::suspend_always
172
172
173
173
virtual bool await_ready () const = 0;
174
174
virtual void await_suspend (coro::coroutine_handle<> h) const = 0;
175
+ virtual void await_resume () const = 0;
175
176
};
176
177
177
178
template <class T >
@@ -192,19 +193,33 @@ class await_async : public coro::suspend_always
192
193
_pimpl->await_suspend (std::move (h));
193
194
}
194
195
196
+ void await_resume () const final
197
+ {
198
+ _pimpl->await_resume ();
199
+ }
200
+
195
201
private:
196
202
std::shared_ptr<T> _pimpl;
197
203
};
198
204
199
205
const std::shared_ptr<Concept> _pimpl;
200
206
201
207
public:
208
+ // Type-erased explicit constructor for a custom awaitable.
202
209
template <class T >
203
- await_async (std::shared_ptr<T> pimpl)
210
+ explicit await_async (std::shared_ptr<T> pimpl)
204
211
: _pimpl { std::make_shared<Model<T>>(std::move (pimpl)) }
205
212
{
206
213
}
207
214
215
+ // Default to immediate synchronous execution.
216
+ await_async ()
217
+ : _pimpl { std::static_pointer_cast<Concept>(
218
+ std::make_shared<Model<coro::suspend_never>>(std::make_shared<coro::suspend_never>())) }
219
+ {
220
+ }
221
+
222
+ // Implicitly convert a std::launch parameter used with std::async to an awaitable.
208
223
await_async (std::launch launch)
209
224
: _pimpl { ((launch & std::launch::async) == std::launch::async)
210
225
? std::static_pointer_cast<Concept>(std::make_shared<Model<await_worker_thread>>(
@@ -224,8 +239,9 @@ class await_async : public coro::suspend_always
224
239
_pimpl->await_suspend (std::move (h));
225
240
}
226
241
227
- constexpr void await_resume () const noexcept
242
+ void await_resume () const
228
243
{
244
+ _pimpl->await_resume ();
229
245
}
230
246
};
231
247
@@ -261,7 +277,7 @@ struct SelectionSetParams
261
277
std::optional<field_path> errorPath;
262
278
263
279
// Async launch policy for sub-field resolvers.
264
- const await_async launch { std::launch::deferred };
280
+ const await_async launch {};
265
281
};
266
282
267
283
// Pass a common bundle of parameters to all of the generated Object::getField accessors.
@@ -931,19 +947,96 @@ GRAPHQLSERVICE_EXPORT AwaitableResolver ModifiedResult<Object>::convert(
931
947
FieldResult<std::shared_ptr<Object>> result, ResolverParams params);
932
948
#endif // GRAPHQL_DLLEXPORTS
933
949
934
- using TypeMap = internal::string_view_map<std::shared_ptr<Object>>;
950
+ // Subscription callbacks receive the response::Value representing the result of evaluating the
951
+ // SelectionSet against the payload.
952
+ using SubscriptionCallback = std::function<void (response::Value)>;
953
+
954
+ // Subscriptions are stored in maps using these keys.
955
+ using SubscriptionKey = size_t ;
956
+ using SubscriptionName = std::string;
957
+
958
+ using AwaitableSubscribe = internal::Awaitable<SubscriptionKey>;
959
+ using AwaitableUnsubscribe = internal::Awaitable<void >;
960
+ using AwaitableDeliver = internal::Awaitable<void >;
935
961
936
- // You can still sub-class RequestState and use that in the state parameter to Request::subscribe
937
- // to add your own state to the service callbacks that you receive while executing the subscription
938
- // query.
939
- struct SubscriptionParams
962
+ struct RequestResolveParams
940
963
{
964
+ // Required query information.
965
+ peg::ast& query;
966
+ std::string_view operationName {};
967
+ response::Value variables { response::Type::Map };
968
+
969
+ // Optional async execution awaitable.
970
+ await_async launch;
971
+
972
+ // Optional sub-class of RequestState which will be passed to each resolver and field accessor.
941
973
std::shared_ptr<RequestState> state;
974
+ };
975
+
976
+ struct RequestSubscribeParams
977
+ {
978
+ // Callback which receives the event data.
979
+ SubscriptionCallback callback;
980
+
981
+ // Required query information.
942
982
peg::ast query;
943
- std::string operationName;
944
- response::Value variables;
983
+ std::string operationName {};
984
+ response::Value variables { response::Type::Map };
985
+
986
+ // Optional async execution awaitable.
987
+ await_async launch;
988
+
989
+ // Optional sub-class of RequestState which will be passed to each resolver and field accessor.
990
+ std::shared_ptr<RequestState> state;
991
+ };
992
+
993
+ struct RequestUnsubscribeParams
994
+ {
995
+ // Key returned by a previous call to subscribe.
996
+ SubscriptionKey key;
997
+
998
+ // Optional async execution awaitable.
999
+ await_async launch;
945
1000
};
946
1001
1002
+ using SubscriptionArguments = std::map<std::string_view, response::Value>;
1003
+ using SubscriptionArgumentFilterCallback = std::function<bool (response::MapType::const_reference)>;
1004
+ using SubscriptionDirectiveFilterCallback = std::function<bool (Directives::const_reference)>;
1005
+
1006
+ struct SubscriptionFilter
1007
+ {
1008
+ // Deliver to subscriptions on this field.
1009
+ std::string_view field;
1010
+
1011
+ // Optional field argument filter, which can either be a set of required arguments, or a
1012
+ // callback which returns true if the arguments match custom criteria.
1013
+ std::optional<std::variant<SubscriptionArguments, SubscriptionArgumentFilterCallback>>
1014
+ arguments;
1015
+
1016
+ // Optional field directives filter, which can either be a set of required directives and
1017
+ // arguments, or a callback which returns true if the directives match custom criteria.
1018
+ std::optional<std::variant<Directives, SubscriptionDirectiveFilterCallback>> directives;
1019
+ };
1020
+
1021
+ // Deliver to a specific subscription key, or apply custom criteria for the field name, arguments,
1022
+ // and directives in the Subscription query.
1023
+ using RequestDeliverFilter = std::optional<std::variant<SubscriptionKey, SubscriptionFilter>>;
1024
+
1025
+ struct RequestDeliverParams
1026
+ {
1027
+ // Optional filter to control which subscriptions will receive the event. If not specified,
1028
+ // every subscription will receive the event and evaluate their queries against it.
1029
+ RequestDeliverFilter filter;
1030
+
1031
+ // Optional async execution awaitable.
1032
+ await_async launch;
1033
+
1034
+ // Optional override for the default Subscription operation object.
1035
+ std::shared_ptr<Object> subscriptionObject;
1036
+ };
1037
+
1038
+ using TypeMap = internal::string_view_map<std::shared_ptr<Object>>;
1039
+
947
1040
// State which is captured and kept alive until all pending futures have been resolved for an
948
1041
// operation. Note: SelectionSet is the other parameter that gets passed to the top level Object,
949
1042
// it's a borrowed reference to an element in the AST. In the case of query and mutation operations,
@@ -961,21 +1054,6 @@ struct OperationData : std::enable_shared_from_this<OperationData>
961
1054
FragmentMap fragments;
962
1055
};
963
1056
964
- // Subscription callbacks receive the response::Value representing the result of evaluating the
965
- // SelectionSet against the payload.
966
- using SubscriptionCallback = std::function<void (response::Value)>;
967
- using SubscriptionArguments = std::map<std::string_view, response::Value>;
968
- using SubscriptionArgumentFilterCallback = std::function<bool (response::MapType::const_reference)>;
969
- using SubscriptionDirectiveFilterCallback = std::function<bool (Directives::const_reference)>;
970
-
971
- // Subscriptions are stored in maps using these keys.
972
- using SubscriptionKey = size_t ;
973
- using SubscriptionName = std::string;
974
-
975
- using AwaitableSubscribe = internal::Awaitable<SubscriptionKey>;
976
- using AwaitableUnsubscribe = internal::Awaitable<void >;
977
- using AwaitableDeliver = internal::Awaitable<void >;
978
-
979
1057
// Registration information for subscription, cached in the Request::subscribe call.
980
1058
struct SubscriptionData : std::enable_shared_from_this<SubscriptionData>
981
1059
{
@@ -1014,51 +1092,17 @@ class Request : public std::enable_shared_from_this<Request>
1014
1092
GRAPHQLSERVICE_EXPORT std::pair<std::string_view, const peg::ast_node*> findOperationDefinition (
1015
1093
peg::ast& query, std::string_view operationName) const ;
1016
1094
1017
- GRAPHQLSERVICE_EXPORT response::AwaitableValue resolve (std::shared_ptr<RequestState> state,
1018
- peg::ast& query, std::string_view operationName, response::Value variables) const ;
1019
- GRAPHQLSERVICE_EXPORT response::AwaitableValue resolve (await_async launch,
1020
- std::shared_ptr<RequestState> state, peg::ast& query, std::string_view operationName,
1021
- response::Value variables) const ;
1022
-
1023
- GRAPHQLSERVICE_EXPORT SubscriptionKey subscribe (
1024
- SubscriptionParams&& params, SubscriptionCallback&& callback);
1025
- GRAPHQLSERVICE_EXPORT AwaitableSubscribe subscribe (
1026
- await_async launch, SubscriptionParams&& params, SubscriptionCallback&& callback);
1027
-
1028
- GRAPHQLSERVICE_EXPORT void unsubscribe (SubscriptionKey key);
1029
- GRAPHQLSERVICE_EXPORT AwaitableUnsubscribe unsubscribe (await_async launch, SubscriptionKey key);
1030
-
1031
- GRAPHQLSERVICE_EXPORT void deliver (
1032
- const SubscriptionName& name, const std::shared_ptr<Object>& subscriptionObject) const ;
1033
- GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
1034
- const SubscriptionArguments& arguments, std::shared_ptr<Object> subscriptionObject) const ;
1035
- GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
1036
- const SubscriptionArguments& arguments, const Directives& directives,
1037
- std::shared_ptr<Object> subscriptionObject) const ;
1038
- GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
1039
- const SubscriptionArgumentFilterCallback& applyArguments,
1040
- std::shared_ptr<Object> subscriptionObject) const ;
1041
- GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
1042
- const SubscriptionArgumentFilterCallback& applyArguments,
1043
- const SubscriptionDirectiveFilterCallback& applyDirectives,
1044
- std::shared_ptr<Object> subscriptionObject) const ;
1045
-
1046
- GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1047
- std::shared_ptr<Object> subscriptionObject) const ;
1048
- GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1049
- const SubscriptionArguments& arguments, std::shared_ptr<Object> subscriptionObject) const ;
1050
- GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1051
- const SubscriptionArguments& arguments, const Directives& directives,
1052
- std::shared_ptr<Object> subscriptionObject) const ;
1053
- GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1054
- const SubscriptionArgumentFilterCallback& applyArguments,
1055
- std::shared_ptr<Object> subscriptionObject) const ;
1056
- GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1057
- const SubscriptionArgumentFilterCallback& applyArguments,
1058
- const SubscriptionDirectiveFilterCallback& applyDirectives,
1059
- std::shared_ptr<Object> subscriptionObject) const ;
1095
+ GRAPHQLSERVICE_EXPORT response::AwaitableValue resolve (RequestResolveParams params) const ;
1096
+ GRAPHQLSERVICE_EXPORT AwaitableSubscribe subscribe (RequestSubscribeParams params);
1097
+ GRAPHQLSERVICE_EXPORT AwaitableUnsubscribe unsubscribe (RequestUnsubscribeParams params);
1098
+ GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (RequestDeliverParams params) const ;
1060
1099
1061
1100
private:
1101
+ SubscriptionKey addSubscription (RequestSubscribeParams&& params);
1102
+ void removeSubscription (SubscriptionKey key);
1103
+ std::vector<std::shared_ptr<SubscriptionData>> collectRegistrations (
1104
+ RequestDeliverFilter&& filter) const noexcept ;
1105
+
1062
1106
const TypeMap _operations;
1063
1107
std::unique_ptr<ValidateExecutableVisitor> _validation;
1064
1108
internal::sorted_map<SubscriptionKey, std::shared_ptr<SubscriptionData>> _subscriptions;
0 commit comments