After sharing this introduction learning journey with my collegues, they asked me to explore how to use subscriptions in order to understand if they could be a feasible solution in an integration scenario where and external system need to respond to some particular events and read data.
in the graphQL server project I've created this subscription
[ExtendObjectType("Subscription")]
public class OrderSubscriptions
{
[Subscribe]
public Order OrderConfirmed([EventMessage] Order order) => order;
}
configured in Program.cs
builder.Services
...
.AddGraphQLServer()
...
.AddInMemorySubscriptions()
.AddSubscriptionType(d => d.Name("Subscription"))
.AddTypeExtension<OrderSubscriptions>()
Here I extended the schema root object with Subscription
part and registered the subscription provider in order to make pub/sub work. HC supports two subscription providers: In-Memory and Redis.
The last step is to enable a suitable transport layer to allow the client to be connected and notified. Here I used web socket:
var app = builder.Build();
app.UseWebSockets();
Then I've created a simple console project that acts as an external system that wants to notify the users when their orders has been confirmed.
# to use Strawberry tools to generate clients
dotnet new tool-manifest
dotnet tool install StrawberryShake.Tools --local
# new GraphQL client project
dotnet new console -n graphqlIntegration
dotnet add ./graphqlIntegration package StrawberryShake --version 12.1.0
dotnet add ./graphqlIntegration package StrawberryShake.Transport.WebSockets --version 12.1.0
dotnet add ./graphqlIntegration package Microsoft.Extensions.Http
dotnet add ./graphqlIntegration package Microsoft.Extensions.DependencyInjection
dotnet sln add graphqlIntegration
In the previous script I've installed StrawberryShake.Tools
that allow to initialize the code generation on the integration project, based on the server schema.
So, I've started the graphQL server project and run the code generation tool.
# run the graphql Server
dotnet run --project .\graphqlServer\
# create the graphqlClient
dotnet graphql init https://localhost:7059/graphql -n graphQlServerClient -p ./graphqlIntegration
Now we have the graphQL schema imported, all the client code generated and the code generation tool enabled in order to automagically update client if new queries are written.
After that, I've written some queries or subscriptions under a folder, like the following:
on-order-confirmed.graphql
:
subscription onOrderConfirmed {
orderConfirmed {
userName
book {
title
}
boughtOn
}
}
when we build the project, the tool will update the client code, so we can use it in our code:
public class OrderConfirmedSubscriber
{
private readonly IgraphQlServerClient _client;
private IDisposable? _subscription;
public OrderConfirmedSubscriber(IgraphQlServerClient client)
{
_client = client ?? throw new ArgumentNullException(nameof(client));
}
public void Start()
=> _subscription = _client
.OnOrderConfirmed
.Watch()
.Subscribe(r =>
{
var order = r.Data!.OrderConfirmed;
Console.WriteLine($@"
Congratulations {order.UserName}!
Your order for ""{order.Book!.Title}"" has been successfully confirmed.
Thank you and come back soon!");
});
public void Stop() => _subscription!.Dispose();
}