在使用Next.js+URQL环境时,使用PostgreSQL的Pub/Sub来进行GraphQL订阅
我在株式会社mofmof工作的shwld,使用Next.js + 服务器端TypeScript + 函数方式创建了一个清洁的应用程序,这篇文章是2022年的Advent Calendar的第21天,我将介绍实现意图等内容。
我之前写过关于如何在Mailgun上实现邮件发送功能的文章。
使用Next.js构建GraphQL Subscription环境。
客户端(next-urql)
withUrqlClient((_ssrExchange, _ctx) => ({
url: `${API_HOST}/api/graphql`,
exchanges: [
dedupExchange,
cache,
fetchExchange,
yogaExchange(),
],
})
原始来源:/apps/web/src/graphql/withGraphQLClient.tsx
中文释义:/apps/web/src/graphql/withGraphQLClient.tsx 的来源
服务器端
Pub/Sub实现
我正在使用 pg-pubsub。
这次我考虑使用PostgreSQL的Pub/Sub功能,原因是为了减少基础设施成本。另外,最初我们没有使用GraphQL Yoga。但是在调研过程中发现有一些免费的Redis,而且后来我们改用了Yoga,所以我觉得如果要正常地实现,使用Redis和Yoga是最好的选择。
由于幸运的是,Pub/Sub客户端的实现已在基础设施层进行,因此迁移变得更简单。
import PGPubsub from 'pg-pubsub';
import type { Pubsub } from 'domain-interfaces';
import asyncify from 'callback-to-async-iterator';
const storyChannelName = (projectId: string) => `project-${projectId}-stories`;
export const createPubsubClient = (): Pubsub => {
const pubsubInstance = new PGPubsub(process.env.DATABASE_URL);
return {
story: {
subscribe({ projectId }) {
return asyncify(async handler => {
pubsubInstance.addChannel(storyChannelName(projectId), handler);
});
},
publish(item) {
pubsubInstance.publish(storyChannelName(item.object.projectId), item);
},
},
};
};
来源:/基础设施/数据库-发布订阅/源代码/索引.ts
订阅
const subscribed = context.pubsub.story.subscribe({
projectId: args.projectId,
});
for await (const it of subscribed) {
if (it.triggeredBy.id === context.currentUser.id) continue;
yield {
subscribeStoryUpdate: it.object,
};
}
来源:/use-cases/graphql-resolvers/src/modules/story/subscription-resolvers/story.update/subscribe-story-update.ts
以下是一种可能的中文释义:
来源:/use-cases/graphql-resolvers/src/modules/story/subscription-resolvers/story.update/subscribe-story-update.ts。
发表
context.pubsub.story.publish({
object: story,
triggeredBy: user,
})
来源:/use-cases/graphql-resolvers/src/modules/story/mutation-resolvers/story.update/update-story.ts#L58-L60
解释:在指定位置的代码文件中,完成“故事更新”功能的地方。
下次会通知你
明天我将写一篇关于背景工作者的文章。