.Net6 + GraphQL + MongoDb 实现Subscription监听功能
介绍
查询、添加、修改我们已经演示了,我们来看下订阅。
订阅大家可以理解为音乐软件, 我们用户 => 订阅音乐频道 <= 服务发送新的音乐通知到频道。 有新的通知进入频道后,频道会推送给客户。
这个东西就和Rxjs一样,在Angular客户端用起来也是一个效果。
正文
修改PostMutation.cs
新增接口
public async Task<AddPostPayload> PublishPost(
[Service] DbContext db,
[Service]ITopicEventSender sender,
AddPostInput input,
CancellationToken cancellationToken)
{
var entity = new Post()
{
Title = input.Title,
Abstraction = "this is an introduction post for graphql",
Content = "some random content for post 1",
Author = input.Author,
PublishedAt = DateTime.Now.AddDays(-2),
Link = "http://link-to-post-1.html",
Comments = new List<Comment>
{
new() { CreatedAt = DateTime.Now, Content = "test comment 03 for post 1", Name = "kindUser02" }
},
};
// await db.Post.InsertOneAsync(entity, cancellationToken: cancellationToken);
await sender.SendAsync(nameof(PublishPost), entity, cancellationToken);
return new AddPostPayload(entity);
}
新建PostSubscription
文件
[Subscribe]
[Topic(nameof(PostMutation.PublishPost))]
public Post OnPublishedPost(
[EventMessage] Post publishedPost)
{
return publishedPost;
}
修改Program
builder.Services
.AddGraphQLServer()
.AddQueryType<PostQuery>()
.AddMutationType<PostMutation>()
.AddSubscriptionType<PostSubscription>()
.AddInMemorySubscriptions()
.AddMongoDbFiltering()
.AddMongoDbSorting()
.AddMongoDbProjections()
.AddMongoDbPagingProviders()
.SetPagingOptions(new PagingOptions
{
MaxPageSize = 50,
IncludeTotalCount = true
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseWebSockets();
app.UseRouting().UseEndpoints(endpoints =>
{
endpoints.MapGraphQL();
});
app.UseGraphQLVoyager("/graphql-voyager", new VoyagerOptions { GraphQLEndPoint = "/graphql" });
这时候我们去https://localhost:7145/graphql/
调用接口,打开2个页面,
A页面调用subscription publishedPost
,调用后客户端会进入订阅状态,等待消息
B页面调用mutation publishPost
,发送消息
mutation publishPost {
publishPost(input: { title:"titl2222e test", author:" author test "}) {
post {
id
}
}
}
subscription publishedPost {
onPublishedPost {
id
title
}
}
高级用法
修改PostSubscription.cs
[Subscribe(With = nameof(OnPublishedStream))]
//[Subscribe]
//[Topic(nameof(PostMutation.PublishPost))]
public Post OnPublishedPost(
[EventMessage] Post publishedPost)
{
return publishedPost;
}
public async IAsyncEnumerable<Post> OnPublishedStream(
[Service] ITopicEventReceiver eventReceiver, [EnumeratorCancellation] CancellationToken cancellationToken)
{
var sourceStream =
await eventReceiver.SubscribeAsync<string, Post>(nameof(PostMutation.PublishPost), cancellationToken);
// 这里理解为去请求数据库拿历史消息
yield return new Post()
{
Title = "subscription Title",
Abstraction = "this is an introduction post for graphql",
Content = "some random content for post 1",
Author = "subscription Author",
PublishedAt = DateTime.Now.AddDays(-2),
Link = "http://link-to-post-1.html",
Comments = new List<Comment>
{
new() { CreatedAt = DateTime.Now, Content = "test comment 03 for post 1", Name = "kindUser02" }
},
};
await Task.Delay(5000, cancellationToken);
await foreach (Post post in sourceStream.ReadEventsAsync())
{
yield return post;
}
}
这时候我们去https://localhost:7145/graphql/
调用接口,打开2个页面,
A页面调用subscription publishedPost
,调用后客户端会立马收到消息subscription Title
这个是等于是历史消息,然后会继续保持订阅状态。当mutation publishPost
调用后会收到发送的消息
B页面调用mutation publishPost
,发送消息。
mutation publishPost {
publishPost(input: { title:"titl2222e test", author:" author test "}) {
post {
id
}
}
}
subscription publishedPost {
onPublishedPost {
id
title
}
}
结语
本系列主要将GraphQL的使用,示例项目不能应用于生产,后续发一些GraphQL库出来讲解生产中的实际应用
联系作者:加群:867095512 @MrChuJiu