Skip to content

Commit 17a9884

Browse files
committed
feat: add visitor APIs
1 parent 8bf5f5d commit 17a9884

File tree

3 files changed

+69
-27
lines changed

3 files changed

+69
-27
lines changed

include/graphqlservice/GraphQLService.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,8 @@ class [[nodiscard("unnecessary construction")]] ResolverVisitor final
516516
virtual void add_float(double value) = 0;
517517

518518
virtual void add_error(schema_error&& error) = 0;
519+
520+
virtual void complete() = 0;
519521
};
520522

521523
template <class T>
@@ -601,6 +603,11 @@ class [[nodiscard("unnecessary construction")]] ResolverVisitor final
601603
_pimpl->add_error(std::move(error));
602604
}
603605

606+
void complete() final
607+
{
608+
_pimpl->complete();
609+
}
610+
604611
private:
605612
std::shared_ptr<T> _pimpl;
606613
};
@@ -635,6 +642,8 @@ class [[nodiscard("unnecessary construction")]] ResolverVisitor final
635642
GRAPHQLSERVICE_EXPORT void add_float(double value);
636643

637644
GRAPHQLSERVICE_EXPORT void add_error(schema_error&& error);
645+
646+
GRAPHQLSERVICE_EXPORT void complete();
638647
};
639648

640649
// Fragments are referenced by name and have a single type condition (except for inline
@@ -779,7 +788,6 @@ struct [[nodiscard("unnecessary construction")]] ResultToken
779788
// we're ready to return from the top level Operation.
780789
struct [[nodiscard("unnecessary construction")]] ResolverResult
781790
{
782-
GRAPHQLSERVICE_EXPORT response::Value toValue() &&;
783791
GRAPHQLSERVICE_EXPORT void visit(const std::shared_ptr<ResolverVisitor>& visitor) &&;
784792

785793
std::list<ResultToken> data {};
@@ -1526,11 +1534,14 @@ using ObjectResult = ModifiedResult<Object>;
15261534
// Subscription callbacks receive the response::Value representing the result of evaluating the
15271535
// SelectionSet against the payload.
15281536
using SubscriptionCallback = std::function<void(response::Value)>;
1537+
using SubscriptionVisitor = std::function<std::shared_ptr<ResolverVisitor>()>;
1538+
using SubscriptionCallbackOrVisitor = std::variant<SubscriptionCallback, SubscriptionVisitor>;
15291539

15301540
// Subscriptions are stored in maps using these keys.
15311541
using SubscriptionKey = std::size_t;
15321542
using SubscriptionName = std::string;
15331543

1544+
using AwaitableVisit = internal::Awaitable<void>;
15341545
using AwaitableSubscribe = internal::Awaitable<SubscriptionKey>;
15351546
using AwaitableUnsubscribe = internal::Awaitable<void>;
15361547
using AwaitableDeliver = internal::Awaitable<void>;
@@ -1552,7 +1563,7 @@ struct [[nodiscard("unnecessary construction")]] RequestResolveParams
15521563
struct [[nodiscard("unnecessary construction")]] RequestSubscribeParams
15531564
{
15541565
// Callback which receives the event data.
1555-
SubscriptionCallback callback;
1566+
SubscriptionCallbackOrVisitor callback;
15561567

15571568
// Required query information.
15581569
peg::ast query;
@@ -1643,7 +1654,7 @@ struct [[nodiscard("unnecessary construction")]] SubscriptionData
16431654
{
16441655
explicit SubscriptionData(std::shared_ptr<OperationData> data, SubscriptionName&& field,
16451656
response::Value arguments, Directives fieldDirectives, peg::ast&& query,
1646-
std::string&& operationName, SubscriptionCallback&& callback,
1657+
std::string&& operationName, SubscriptionCallbackOrVisitor&& callback,
16471658
const peg::ast_node& selection);
16481659

16491660
std::shared_ptr<OperationData> data;
@@ -1653,7 +1664,7 @@ struct [[nodiscard("unnecessary construction")]] SubscriptionData
16531664
Directives fieldDirectives;
16541665
peg::ast query;
16551666
std::string operationName;
1656-
SubscriptionCallback callback;
1667+
SubscriptionCallbackOrVisitor callback;
16571668
const peg::ast_node& selection;
16581669
};
16591670

@@ -1688,6 +1699,8 @@ class [[nodiscard("unnecessary construction")]] Request
16881699

16891700
[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT response::AwaitableValue resolve(
16901701
RequestResolveParams params) const;
1702+
[[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT AwaitableVisit visit(
1703+
RequestResolveParams params, const std::shared_ptr<ResolverVisitor>& resolverVisitor) const;
16911704
[[nodiscard("leaked subscription")]] GRAPHQLSERVICE_EXPORT AwaitableSubscribe subscribe(
16921705
RequestSubscribeParams params);
16931706
[[nodiscard("potentially leaked subscription")]] GRAPHQLSERVICE_EXPORT AwaitableUnsubscribe

include/graphqlservice/Service.ixx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,12 @@ using modified_result::ScalarResult;
103103
using modified_result::ObjectResult;
104104

105105
using service::SubscriptionCallback;
106+
using service::SubscriptionVisitor;
107+
using service::SubscriptionCallbackOrVisitor;
106108
using service::SubscriptionKey;
107109
using service::SubscriptionName;
108110

111+
using service::AwaitableVisit;
109112
using service::AwaitableSubscribe;
110113
using service::AwaitableUnsubscribe;
111114
using service::AwaitableDeliver;

src/GraphQLService.cpp

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,11 @@ void ResolverVisitor::add_error(schema_error&& error)
349349
_concept->add_error(std::move(error));
350350
}
351351

352+
void ResolverVisitor::complete()
353+
{
354+
_concept->complete();
355+
}
356+
352357
FieldParams::FieldParams(SelectionSetParams&& selectionSetParams, Directives directives)
353358
: SelectionSetParams(std::move(selectionSetParams))
354359
, fieldDirectives(std::move(directives))
@@ -852,6 +857,7 @@ class ResolverResultVisitor
852857
void add_int(int value);
853858
void add_float(double value);
854859
void add_error(schema_error&& error);
860+
void complete();
855861

856862
response::Value document();
857863

@@ -952,6 +958,10 @@ void ResolverResultVisitor::add_error(schema_error&& error)
952958
_errors.push_back(std::move(error));
953959
}
954960

961+
void ResolverResultVisitor::complete()
962+
{
963+
}
964+
955965
response::Value ResolverResultVisitor::document()
956966
{
957967
response::Value document { response::Type::Map };
@@ -991,15 +1001,6 @@ void ResolverResultVisitor::add_value(response::Value&& value)
9911001
}
9921002
}
9931003

994-
response::Value ResolverResult::toValue() &&
995-
{
996-
auto visitor = std::make_shared<ResolverResultVisitor>();
997-
998-
(std::move(*this)).visit(std::make_shared<ResolverVisitor>(visitor));
999-
1000-
return visitor->document();
1001-
}
1002-
10031004
void ResolverResult::visit(const std::shared_ptr<ResolverVisitor>& visitor) &&
10041005
{
10051006
for (auto& token : data)
@@ -1011,6 +1012,8 @@ void ResolverResult::visit(const std::shared_ptr<ResolverVisitor>& visitor) &&
10111012
{
10121013
visitor->add_error(std::move(error));
10131014
}
1015+
1016+
visitor->complete();
10141017
}
10151018

10161019
template <>
@@ -1857,7 +1860,8 @@ void OperationDefinitionVisitor::visit(
18571860

18581861
SubscriptionData::SubscriptionData(std::shared_ptr<OperationData> data, SubscriptionName&& field,
18591862
response::Value arguments, Directives fieldDirectives, peg::ast&& query,
1860-
std::string&& operationName, SubscriptionCallback&& callback, const peg::ast_node& selection)
1863+
std::string&& operationName, SubscriptionCallbackOrVisitor&& callback,
1864+
const peg::ast_node& selection)
18611865
: data(std::move(data))
18621866
, field(std::move(field))
18631867
, arguments(std::move(arguments))
@@ -2154,6 +2158,15 @@ std::pair<std::string_view, const peg::ast_node*> Request::findOperationDefiniti
21542158
}
21552159

21562160
response::AwaitableValue Request::resolve(RequestResolveParams params) const
2161+
{
2162+
auto visitor = std::make_shared<ResolverResultVisitor>();
2163+
2164+
co_await visit(std::move(params), std::make_shared<ResolverVisitor>(visitor));
2165+
co_return visitor->document();
2166+
}
2167+
2168+
AwaitableVisit Request::visit(
2169+
RequestResolveParams params, const std::shared_ptr<ResolverVisitor>& resolverVisitor) const
21572170
{
21582171
try
21592172
{
@@ -2210,16 +2223,13 @@ response::AwaitableValue Request::resolve(RequestResolveParams params) const
22102223
co_await params.launch;
22112224
operationVisitor.visit(operationType, *operationDefinition);
22122225

2213-
co_return (co_await operationVisitor.getValue()).toValue();
2226+
(co_await operationVisitor.getValue()).visit(resolverVisitor);
22142227
}
22152228
catch (schema_exception& ex)
22162229
{
2217-
response::Value document(response::Type::Map);
2230+
ResolverResult document { {}, ex.getStructuredErrors() };
22182231

2219-
document.emplace_back(std::string { strData }, response::Value());
2220-
document.emplace_back(std::string { strErrors }, ex.getErrors());
2221-
2222-
co_return std::move(document);
2232+
std::move(document).visit(resolverVisitor);
22232233
}
22242234
}
22252235

@@ -2380,26 +2390,42 @@ AwaitableDeliver Request::deliver(RequestDeliverParams params) const
23802390
params.launch,
23812391
};
23822392

2383-
response::Value document { response::Type::Map };
2393+
ResolverResult document {};
23842394

23852395
try
23862396
{
23872397
co_await params.launch;
23882398

2389-
auto result = co_await optionalOrDefaultSubscription->resolve(selectionSetParams,
2399+
document = co_await optionalOrDefaultSubscription->resolve(selectionSetParams,
23902400
registration->selection,
23912401
registration->data->fragments,
23922402
registration->data->variables);
2393-
2394-
document = std::move(result).toValue();
23952403
}
23962404
catch (schema_exception& ex)
23972405
{
2398-
document.emplace_back(std::string { strData }, response::Value());
2399-
document.emplace_back(std::string { strErrors }, ex.getErrors());
2406+
document.errors.splice(document.errors.end(), ex.getStructuredErrors());
24002407
}
24012408

2402-
registration->callback(std::move(document));
2409+
std::visit(
2410+
[result = std::move(document)](const auto& callback) mutable {
2411+
using callback_type = std::decay_t<decltype(callback)>;
2412+
2413+
if constexpr (std::is_same_v<callback_type, SubscriptionCallback>)
2414+
{
2415+
auto visitor = std::make_shared<ResolverResultVisitor>();
2416+
2417+
(std::move(result)).visit(std::make_shared<ResolverVisitor>(visitor));
2418+
2419+
callback(visitor->document());
2420+
}
2421+
else if constexpr (std::is_same_v<callback_type, SubscriptionVisitor>)
2422+
{
2423+
auto visitor = callback();
2424+
2425+
(std::move(result)).visit(visitor);
2426+
}
2427+
},
2428+
registration->callback);
24032429
}
24042430

24052431
co_return;

0 commit comments

Comments
 (0)