Subscriptionlar
Querylar orqali ma'lumot olish va mutatsiyalar orqali ma'lumotni o'zgartirishdan tashqari, GraphQL spetsifikatsiyasi subscription deb ataladigan uchinchi operatsiya turini ham qo'l
Querylar orqali ma'lumot olish va mutatsiyalar orqali ma'lumotni o'zgartirishdan tashqari, GraphQL spetsifikatsiyasi subscription deb ataladigan uchinchi operatsiya turini ham qo'llab-quvvatlaydi. GraphQL subscriptionlari - serverdan real time xabarlarni tinglashni tanlagan klientlarga serverdan ma'lumot yuborish usuli. Subscriptionlar querylarga o'xshaydi: ular klientga yetkaziladigan fieldlar to'plamini belgilaydi, ammo bitta javobni darhol qaytarish o'rniga kanal ochiladi va serverda muayyan hodisa sodir bo'lganda har safar natija klientga yuboriladi.
Subscriptionlar uchun keng tarqalgan use case - klient tomonni muayyan hodisalar haqida xabardor qilish, masalan yangi obyekt yaratilishi, fieldlar yangilanishi va h.k. (batafsil bu yerda).
Apollo driver bilan subscriptionlarni yoqish
Subscriptionlarni yoqish uchun installSubscriptionHandlers xossasini true qiling.
1GraphQLModule.forRoot<ApolloDriverConfig>({
2 driver: ApolloDriver,
3 installSubscriptionHandlers: true,
4}),installSubscriptionHandlers konfiguratsiya opsiyasi Apollo serverning so'nggi versiyasidan olib tashlangan va bu paketda ham tez orada deprecate qilinadi. Default holatda installSubscriptionHandlerssubscriptions-transport-wsga fallback qiladi (batafsil), ammo biz graphql-ws (batafsil) kutubxonasidan foydalanishni qat'iy tavsiya qilamiz.
Buning o'rniga graphql-ws paketidan foydalanish uchun quyidagi konfiguratsiyani ishlating:
1GraphQLModule.forRoot<ApolloDriverConfig>({
2 driver: ApolloDriver,
3 subscriptions: {
4 'graphql-ws': true
5 },
6}),Orqaga moslik uchun subscriptions-transport-ws va graphql-ws ni bir vaqtda ishlatishingiz ham mumkin.
Code first
Code first yondashuvida subscription yaratish uchun @Subscription() dekoratoridan (@nestjs/graphql paketidan eksport qilinadi) va graphql-subscriptions paketidagi PubSub klassidan foydalanamiz; u oddiy publish/subscribe API taqdim etadi.
Quyidagi subscription handler PubSub#asyncIterableIterator chaqiruvi orqali hodisaga obuna bo'ladi. Bu metod bitta argument qabul qiladi - triggerName, ya'ni event topic nomi.
1const pubSub = new PubSub();
2
3@Resolver(() => Author)
4export class AuthorResolver {
5 // ...
6 @Subscription(() => Comment)
7 commentAdded() {
8 return pubSub.asyncIterableIterator('commentAdded');
9 }
10}Barcha dekoratorlar @nestjs/graphql paketidan, PubSub klassi esa graphql-subscriptions paketidan eksport qilinadi.
PubSub oddiy publish va subscribe API taqdim etadigan klass. Bu haqida bu yerda batafsil o'qing. Apollo hujjatlarida default implementatsiya production uchun mos emasligi haqida ogohlantiriladi (batafsil). Production ilovalarida tashqi storega tayanadigan PubSub implementatsiyasidan foydalanish kerak (batafsil).
Bu SDLda quyidagi qismini generatsiya qiladi:
1type Subscription {
2 commentAdded(): Comment!
3}Subscriptionlar ta'rifi bo'yicha bitta top-level xossaga ega obyekt qaytaradi; bu xossaning kaliti subscription nomi bo'ladi. Bu nom yoki subscription handler metodi nomidan olinadi (yuqorida commentAdded) yoki @Subscription() dekoratoriga ikkinchi argument sifatida name kalitli opsiya berib aniq ko'rsatiladi:
1@Subscription(() => Comment, {
2 name: 'commentAdded',
3})
4subscribeToCommentAdded() {
5 return pubSub.asyncIterableIterator('commentAdded');
6}Bu konstruktsiya avvalgi kod namunasidagi kabi SDLni hosil qiladi, ammo metod nomini subscriptiondan ajratishga imkon beradi.
Publishing
Endi hodisani publish qilish uchun PubSub#publish metodidan foydalanamiz. Bu ko'pincha mutatsiya ichida, obyekt graphning bir qismi o'zgarganda klient tomondagi yangilanishni ishga tushirish uchun ishlatiladi. Masalan:
1@Mutation(() => Comment)
2async addComment(
3 @Args('postId', { type: () => Int }) postId: number,
4 @Args('comment', { type: () => Comment }) comment: CommentInput,
5) {
6 const newComment = this.commentsService.addComment({ id: postId, comment });
7 pubSub.publish('commentAdded', { commentAdded: newComment });
8 return newComment;
9}PubSub#publish metodi birinchi parametr sifatida triggerName (event topic nomi) va ikkinchi parametr sifatida event payloadini qabul qiladi. Avval aytilganidek, subscription ta'rifi bo'yicha qiymat qaytaradi va bu qiymat ma'lum shaklga ega. commentAdded subscriptioni uchun generatsiya qilingan SDLga yana bir qarang:
1type Subscription {
2 commentAdded(): Comment!
3}Bu subscription commentAdded nomli top-level xossaga ega obyekt qaytarishi va bu xossa qiymati Comment obyektidan iborat bo'lishi kerakligini bildiradi. Muhim nuqta shuki, PubSub#publish orqali yuboriladigan event payloadi subscriptiondan qaytadigan qiymat shakliga mos bo'lishi kerak. Shuning uchun yuqoridagi misolda pubSub.publish('commentAdded', {{ '{' }} commentAdded: newComment {{ '}' }}) operatori mos shakldagi payload bilan commentAdded eventini publish qiladi. Agar bu shakllar mos kelmasa, subscription GraphQL validation bosqichida muvaffaqiyatsiz bo'ladi.
Subscriptionlarni filtrlash
Muayyan eventlarni filtrlash uchun filter xossasiga filter funksiyasini bering. Bu funksiya array filter ga o'xshash ishlaydi. U ikkita argument oladi: event payloadini o'z ichiga olgan payload (publish qilingan) va subscription so'rovida uzatilgan argumentlarni o'z ichiga olgan variables. Funksiya bu event klientlar uchun publish qilinishi kerakmi-yo'qligini belgilovchi boolean qaytaradi.
1@Subscription(() => Comment, {
2 filter: (payload, variables) =>
3 payload.commentAdded.title === variables.title,
4})
5commentAdded(@Args('title') title: string) {
6 return pubSub.asyncIterableIterator('commentAdded');
7}Subscription payloadini o'zgartirish
Publish qilingan event payloadini o'zgartirish uchun resolve xossasiga funksiya bering. Funksiya event payloadini (publish qilingan) qabul qiladi va mos qiymatni qaytaradi.
1@Subscription(() => Comment, {
2 resolve: value => value,
3})
4commentAdded() {
5 return pubSub.asyncIterableIterator('commentAdded');
6}Agar resolve opsiyasidan foydalansangiz, unwrapped payloadni qaytarishingiz kerak (bizning misolda {{ '{' }} commentAdded: newComment {{ '}' }} emas, to'g'ridan-to'g'ri newComment obyektini qaytaring).
Agar injected providerlarga kirish kerak bo'lsa (masalan, ma'lumotni tekshirish uchun tashqi servisni chaqirish), quyidagi konstruktsiyadan foydalaning.
1@Subscription(() => Comment, {
2 resolve(this: AuthorResolver, value) {
3 // "this" refers to an instance of "AuthorResolver"
4 return value;
5 }
6})
7commentAdded() {
8 return pubSub.asyncIterableIterator('commentAdded');
9}Xuddi shu konstruktsiya filtrlarda ham ishlaydi:
1@Subscription(() => Comment, {
2 filter(this: AuthorResolver, payload, variables) {
3 // "this" refers to an instance of "AuthorResolver"
4 return payload.commentAdded.title === variables.title;
5 }
6})
7commentAdded() {
8 return pubSub.asyncIterableIterator('commentAdded');
9}Schema first
Nestda shunga teng subscription yaratish uchun @Subscription() dekoratoridan foydalanamiz.
1const pubSub = new PubSub();
2
3@Resolver('Author')
4export class AuthorResolver {
5 // ...
6 @Subscription()
7 commentAdded() {
8 return pubSub.asyncIterableIterator('commentAdded');
9 }
10}Muayyan eventlarni context va argumentlar bo'yicha filtrlash uchun filter xossasini bering.
1@Subscription('commentAdded', {
2 filter: (payload, variables) =>
3 payload.commentAdded.title === variables.title,
4})
5commentAdded() {
6 return pubSub.asyncIterableIterator('commentAdded');
7}Published payloadni o'zgartirish uchun resolve funksiyasidan foydalanamiz.
1@Subscription('commentAdded', {
2 resolve: value => value,
3})
4commentAdded() {
5 return pubSub.asyncIterableIterator('commentAdded');
6}Agar injected providerlarga kirish kerak bo'lsa (masalan, ma'lumotni tekshirish uchun tashqi servisni chaqirish), quyidagi konstruktsiyadan foydalaning:
1@Subscription('commentAdded', {
2 resolve(this: AuthorResolver, value) {
3 // "this" refers to an instance of "AuthorResolver"
4 return value;
5 }
6})
7commentAdded() {
8 return pubSub.asyncIterableIterator('commentAdded');
9}Xuddi shu konstruktsiya filtrlarda ham ishlaydi:
1@Subscription('commentAdded', {
2 filter(this: AuthorResolver, payload, variables) {
3 // "this" refers to an instance of "AuthorResolver"
4 return payload.commentAdded.title === variables.title;
5 }
6})
7commentAdded() {
8 return pubSub.asyncIterableIterator('commentAdded');
9}Oxirgi qadam - type definitions faylini yangilash.
1type Author {
2 id: Int!
3 firstName: String
4 lastName: String
5 posts: [Post]
6}
7
8type Post {
9 id: Int!
10 title: String
11 votes: Int
12}
13
14type Query {
15 author(id: Int!): Author
16}
17
18type Comment {
19 id: String
20 content: String
21}
22
23type Subscription {
24 commentAdded(title: String!): Comment
25}Shu bilan biz bitta commentAdded(title: String!): Comment subscription yaratdik. To'liq namuna implementatsiyani bu yerda topasiz.
PubSub
Yuqoridagi misollarda default PubSub emitteridan foydalandik (mqemitter).
Afzal yondashuv (production uchun) - mqemitter-redisdan foydalanish. Muqobil ravishda, custom PubSub implementatsiyasini ham berishingiz mumkin (batafsil).
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: {
4 emitter: require('mqemitter-redis')({
5 port: 6579,
6 host: '127.0.0.1',
7 }),
8 },
9});WebSocket orqali autentifikatsiya
Foydalanuvchi autentifikatsiyadan o'tganini tekshirish subscription opsiyalarida ko'rsatiladigan verifyClient callback funksiyasi ichida bajarilishi mumkin.
verifyClient birinchi argument sifatida info obyektini oladi; undan so'rov headerlarini olish uchun foydalanishingiz mumkin.
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: {
4 verifyClient: (info, next) => {
5 const authorization = info.req.headers?.authorization as string;
6 if (!authorization?.startsWith('Bearer ')) {
7 return next(false);
8 }
9 next(true);
10 },
11 }
12}),Mercurius driver bilan subscriptionlarni yoqish
Subscriptionlarni yoqish uchun subscription xossasini true qiling.
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: true,
4}),Custom emitter sozlash, kiruvchi ulanishlarni validatsiya qilish va h.k. uchun opsiyalar obyektini ham uzatishingiz mumkin. Batafsil bu yerda o'qing (subscription bo'limi).
Code first
Code first yondashuvida subscription yaratish uchun @Subscription() dekoratoridan (@nestjs/graphql paketidan eksport qilinadi) va mercurius paketidagi PubSub klassidan foydalanamiz; u oddiy publish/subscribe API taqdim etadi.
Quyidagi subscription handler PubSub#asyncIterableIterator chaqiruvi orqali hodisaga obuna bo'ladi. Bu metod bitta argument qabul qiladi - triggerName, ya'ni event topic nomi.
1@Resolver(() => Author)
2export class AuthorResolver {
3 // ...
4 @Subscription(() => Comment)
5 commentAdded(@Context('pubsub') pubSub: PubSub) {
6 return pubSub.subscribe('commentAdded');
7 }
8}Yuqoridagi misolda ishlatilgan barcha dekoratorlar @nestjs/graphql paketidan eksport qilinadi, PubSub klassi esa mercurius paketidan eksport qilinadi.
PubSub oddiy publish va subscribe API taqdim etadigan klass. Ushbu bo'limda custom PubSub klassini qanday ro'yxatdan o'tkazish ko'rsatilgan.
Bu SDLda quyidagi qismini generatsiya qiladi:
1type Subscription {
2 commentAdded(): Comment!
3}Subscriptionlar ta'rifi bo'yicha bitta top-level xossaga ega obyekt qaytaradi; bu xossaning kaliti subscription nomi bo'ladi. Bu nom yoki subscription handler metodi nomidan olinadi (yuqorida commentAdded) yoki @Subscription() dekoratoriga ikkinchi argument sifatida name kalitli opsiya berib aniq ko'rsatiladi:
1@Subscription(() => Comment, {
2 name: 'commentAdded',
3})
4subscribeToCommentAdded(@Context('pubsub') pubSub: PubSub) {
5 return pubSub.subscribe('commentAdded');
6}Bu konstruktsiya avvalgi kod namunasidagi kabi SDLni hosil qiladi, ammo metod nomini subscriptiondan ajratishga imkon beradi.
Publishing
Endi hodisani publish qilish uchun PubSub#publish metodidan foydalanamiz. Bu ko'pincha mutatsiya ichida, obyekt graphning bir qismi o'zgarganda klient tomondagi yangilanishni ishga tushirish uchun ishlatiladi. Masalan:
1@Mutation(() => Comment)
2async addComment(
3 @Args('postId', { type: () => Int }) postId: number,
4 @Args('comment', { type: () => Comment }) comment: CommentInput,
5 @Context('pubsub') pubSub: PubSub,
6) {
7 const newComment = this.commentsService.addComment({ id: postId, comment });
8 await pubSub.publish({
9 topic: 'commentAdded',
10 payload: {
11 commentAdded: newComment
12 }
13 });
14 return newComment;
15}Avval aytilganidek, subscription ta'rifi bo'yicha qiymat qaytaradi va bu qiymat ma'lum shaklga ega. commentAdded subscriptioni uchun generatsiya qilingan SDLga yana bir qarang:
1type Subscription {
2 commentAdded(): Comment!
3}Bu subscription commentAdded nomli top-level xossaga ega obyekt qaytarishi va bu xossa qiymati Comment obyektidan iborat bo'lishi kerakligini bildiradi. Muhim nuqta shuki, PubSub#publish orqali yuboriladigan event payloadi subscriptiondan qaytadigan qiymat shakliga mos bo'lishi kerak. Shuning uchun yuqoridagi misolda pubSub.publish({{ '{' }} topic: 'commentAdded', payload: {{ '{' }} commentAdded: newComment {{ '}' }} {{ '}' }}) operatori mos shakldagi payload bilan commentAdded eventini publish qiladi. Agar bu shakllar mos kelmasa, subscription GraphQL validation bosqichida muvaffaqiyatsiz bo'ladi.
Subscriptionlarni filtrlash
Muayyan eventlarni filtrlash uchun filter xossasiga filter funksiyasini bering. Bu funksiya array filter ga o'xshash ishlaydi. U ikkita argument oladi: event payloadini o'z ichiga olgan payload (publish qilingan) va subscription so'rovida uzatilgan argumentlarni o'z ichiga olgan variables. Funksiya bu event klientlar uchun publish qilinishi kerakmi-yo'qligini belgilovchi boolean qaytaradi.
1@Subscription(() => Comment, {
2 filter: (payload, variables) =>
3 payload.commentAdded.title === variables.title,
4})
5commentAdded(@Args('title') title: string, @Context('pubsub') pubSub: PubSub) {
6 return pubSub.subscribe('commentAdded');
7}Agar injected providerlarga kirish kerak bo'lsa (masalan, ma'lumotni tekshirish uchun tashqi servisni chaqirish), quyidagi konstruktsiyadan foydalaning.
1@Subscription(() => Comment, {
2 filter(this: AuthorResolver, payload, variables) {
3 // "this" refers to an instance of "AuthorResolver"
4 return payload.commentAdded.title === variables.title;
5 }
6})
7commentAdded(@Args('title') title: string, @Context('pubsub') pubSub: PubSub) {
8 return pubSub.subscribe('commentAdded');
9}Schema first
Nestda shunga teng subscription yaratish uchun @Subscription() dekoratoridan foydalanamiz.
1const pubSub = new PubSub();
2
3@Resolver('Author')
4export class AuthorResolver {
5 // ...
6 @Subscription()
7 commentAdded(@Context('pubsub') pubSub: PubSub) {
8 return pubSub.subscribe('commentAdded');
9 }
10}Muayyan eventlarni context va argumentlar bo'yicha filtrlash uchun filter xossasini bering.
1@Subscription('commentAdded', {
2 filter: (payload, variables) =>
3 payload.commentAdded.title === variables.title,
4})
5commentAdded(@Context('pubsub') pubSub: PubSub) {
6 return pubSub.subscribe('commentAdded');
7}Agar injected providerlarga kirish kerak bo'lsa (masalan, ma'lumotni tekshirish uchun tashqi servisni chaqirish), quyidagi konstruktsiyadan foydalaning:
1@Subscription('commentAdded', {
2 filter(this: AuthorResolver, payload, variables) {
3 // "this" refers to an instance of "AuthorResolver"
4 return payload.commentAdded.title === variables.title;
5 }
6})
7commentAdded(@Context('pubsub') pubSub: PubSub) {
8 return pubSub.subscribe('commentAdded');
9}Oxirgi qadam - type definitions faylini yangilash.
1type Author {
2 id: Int!
3 firstName: String
4 lastName: String
5 posts: [Post]
6}
7
8type Post {
9 id: Int!
10 title: String
11 votes: Int
12}
13
14type Query {
15 author(id: Int!): Author
16}
17
18type Comment {
19 id: String
20 content: String
21}
22
23type Subscription {
24 commentAdded(title: String!): Comment
25}Shu bilan biz bitta commentAdded(title: String!): Comment subscription yaratdik.
PubSub
Yuqoridagi misollarda default PubSub emitteridan foydalandik (mqemitter).
Afzal yondashuv (production uchun) - mqemitter-redisdan foydalanish. Muqobil ravishda, custom PubSub implementatsiyasini ham berishingiz mumkin (batafsil).
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: {
4 emitter: require('mqemitter-redis')({
5 port: 6579,
6 host: '127.0.0.1',
7 }),
8 },
9});WebSocket orqali autentifikatsiya
Foydalanuvchi autentifikatsiyadan o'tganini tekshirish subscription opsiyalarida ko'rsatiladigan verifyClient callback funksiyasi ichida bajarilishi mumkin.
verifyClient birinchi argument sifatida info obyektini oladi; undan so'rov headerlarini olish uchun foydalanishingiz mumkin.
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: {
4 verifyClient: (info, next) => {
5 const authorization = info.req.headers?.authorization as string;
6 if (!authorization?.startsWith('Bearer ')) {
7 return next(false);
8 }
9 next(true);
10 },
11 }
12}),Mercurius driver bilan subscriptionlarni yoqish
Subscriptionlarni yoqish uchun subscription xossasini true qiling.
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: true,
4}),Custom emitter sozlash, kiruvchi ulanishlarni validatsiya qilish va h.k. uchun opsiyalar obyektini ham uzatishingiz mumkin. Batafsil bu yerda o'qing (subscription bo'limi).
Code first
Code first yondashuvida subscription yaratish uchun @Subscription() dekoratoridan (@nestjs/graphql paketidan eksport qilinadi) va mercurius paketidagi PubSub klassidan foydalanamiz; u oddiy publish/subscribe API taqdim etadi.
Quyidagi subscription handler PubSub#asyncIterableIterator chaqiruvi orqali hodisaga obuna bo'ladi. Bu metod bitta argument qabul qiladi - triggerName, ya'ni event topic nomi.
1@Resolver(() => Author)
2export class AuthorResolver {
3 // ...
4 @Subscription(() => Comment)
5 commentAdded(@Context('pubsub') pubSub: PubSub) {
6 return pubSub.subscribe('commentAdded');
7 }
8}Yuqoridagi misolda ishlatilgan barcha dekoratorlar @nestjs/graphql paketidan eksport qilinadi, PubSub klassi esa mercurius paketidan eksport qilinadi.
PubSub oddiy publish va subscribe API taqdim etadigan klass. Ushbu bo'limda custom PubSub klassini qanday ro'yxatdan o'tkazish ko'rsatilgan.
Bu SDLda quyidagi qismini generatsiya qiladi:
1type Subscription {
2 commentAdded(): Comment!
3}Subscriptionlar ta'rifi bo'yicha bitta top-level xossaga ega obyekt qaytaradi; bu xossaning kaliti subscription nomi bo'ladi. Bu nom yoki subscription handler metodi nomidan olinadi (yuqorida commentAdded) yoki @Subscription() dekoratoriga ikkinchi argument sifatida name kalitli opsiya berib aniq ko'rsatiladi:
1@Subscription(() => Comment, {
2 name: 'commentAdded',
3})
4subscribeToCommentAdded(@Context('pubsub') pubSub: PubSub) {
5 return pubSub.subscribe('commentAdded');
6}Bu konstruktsiya avvalgi kod namunasidagi kabi SDLni hosil qiladi, ammo metod nomini subscriptiondan ajratishga imkon beradi.
Publishing
Endi hodisani publish qilish uchun PubSub#publish metodidan foydalanamiz. Bu ko'pincha mutatsiya ichida, obyekt graphning bir qismi o'zgarganda klient tomondagi yangilanishni ishga tushirish uchun ishlatiladi. Masalan:
1@Mutation(() => Comment)
2async addComment(
3 @Args('postId', { type: () => Int }) postId: number,
4 @Args('comment', { type: () => Comment }) comment: CommentInput,
5 @Context('pubsub') pubSub: PubSub,
6) {
7 const newComment = this.commentsService.addComment({ id: postId, comment });
8 await pubSub.publish({
9 topic: 'commentAdded',
10 payload: {
11 commentAdded: newComment
12 }
13 });
14 return newComment;
15}Avval aytilganidek, subscription ta'rifi bo'yicha qiymat qaytaradi va bu qiymat ma'lum shaklga ega. commentAdded subscriptioni uchun generatsiya qilingan SDLga yana bir qarang:
1type Subscription {
2 commentAdded(): Comment!
3}Bu subscription commentAdded nomli top-level xossaga ega obyekt qaytarishi va bu xossa qiymati Comment obyektidan iborat bo'lishi kerakligini bildiradi. Muhim nuqta shuki, PubSub#publish orqali yuboriladigan event payloadi subscriptiondan qaytadigan qiymat shakliga mos bo'lishi kerak. Shuning uchun yuqoridagi misolda pubSub.publish({{ '{' }} topic: 'commentAdded', payload: {{ '{' }} commentAdded: newComment {{ '}' }} {{ '}' }}) operatori mos shakldagi payload bilan commentAdded eventini publish qiladi. Agar bu shakllar mos kelmasa, subscription GraphQL validation bosqichida muvaffaqiyatsiz bo'ladi.
Subscriptionlarni filtrlash
Muayyan eventlarni filtrlash uchun filter xossasiga filter funksiyasini bering. Bu funksiya array filter ga o'xshash ishlaydi. U ikkita argument oladi: event payloadini o'z ichiga olgan payload (publish qilingan) va subscription so'rovida uzatilgan argumentlarni o'z ichiga olgan variables. Funksiya bu event klientlar uchun publish qilinishi kerakmi-yo'qligini belgilovchi boolean qaytaradi.
1@Subscription(() => Comment, {
2 filter: (payload, variables) =>
3 payload.commentAdded.title === variables.title,
4})
5commentAdded(@Args('title') title: string, @Context('pubsub') pubSub: PubSub) {
6 return pubSub.subscribe('commentAdded');
7}Agar injected providerlarga kirish kerak bo'lsa (masalan, ma'lumotni tekshirish uchun tashqi servisni chaqirish), quyidagi konstruktsiyadan foydalaning.
1@Subscription(() => Comment, {
2 filter(this: AuthorResolver, payload, variables) {
3 // "this" refers to an instance of "AuthorResolver"
4 return payload.commentAdded.title === variables.title;
5 }
6})
7commentAdded(@Args('title') title: string, @Context('pubsub') pubSub: PubSub) {
8 return pubSub.subscribe('commentAdded');
9}Schema first
Nestda shunga teng subscription yaratish uchun @Subscription() dekoratoridan foydalanamiz.
1const pubSub = new PubSub();
2
3@Resolver('Author')
4export class AuthorResolver {
5 // ...
6 @Subscription()
7 commentAdded(@Context('pubsub') pubSub: PubSub) {
8 return pubSub.subscribe('commentAdded');
9 }
10}Muayyan eventlarni context va argumentlar bo'yicha filtrlash uchun filter xossasini bering.
1@Subscription('commentAdded', {
2 filter: (payload, variables) =>
3 payload.commentAdded.title === variables.title,
4})
5commentAdded(@Context('pubsub') pubSub: PubSub) {
6 return pubSub.subscribe('commentAdded');
7}Agar injected providerlarga kirish kerak bo'lsa (masalan, ma'lumotni tekshirish uchun tashqi servisni chaqirish), quyidagi konstruktsiyadan foydalaning:
1@Subscription('commentAdded', {
2 filter(this: AuthorResolver, payload, variables) {
3 // "this" refers to an instance of "AuthorResolver"
4 return payload.commentAdded.title === variables.title;
5 }
6})
7commentAdded(@Context('pubsub') pubSub: PubSub) {
8 return pubSub.subscribe('commentAdded');
9}Oxirgi qadam - type definitions faylini yangilash.
1type Author {
2 id: Int!
3 firstName: String
4 lastName: String
5 posts: [Post]
6}
7
8type Post {
9 id: Int!
10 title: String
11 votes: Int
12}
13
14type Query {
15 author(id: Int!): Author
16}
17
18type Comment {
19 id: String
20 content: String
21}
22
23type Subscription {
24 commentAdded(title: String!): Comment
25}Shu bilan biz bitta commentAdded(title: String!): Comment subscription yaratdik.
PubSub
Yuqoridagi misollarda default PubSub emitteridan foydalandik (mqemitter).
Afzal yondashuv (production uchun) - mqemitter-redisdan foydalanish. Muqobil ravishda, custom PubSub implementatsiyasini ham berishingiz mumkin (batafsil).
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: {
4 emitter: require('mqemitter-redis')({
5 port: 6579,
6 host: '127.0.0.1',
7 }),
8 },
9});WebSocket orqali autentifikatsiya
Foydalanuvchi autentifikatsiyadan o'tganini tekshirish subscription opsiyalarida ko'rsatiladigan verifyClient callback funksiyasi ichida bajarilishi mumkin.
verifyClient birinchi argument sifatida info obyektini oladi; undan so'rov headerlarini olish uchun foydalanishingiz mumkin.
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: {
4 verifyClient: (info, next) => {
5 const authorization = info.req.headers?.authorization as string;
6 if (!authorization?.startsWith('Bearer ')) {
7 return next(false);
8 }
9 next(true);
10 },
11 }
12}),Mercurius driver bilan subscriptionlarni yoqish
Subscriptionlarni yoqish uchun subscription xossasini true qiling.
1GraphQLModule.forRoot<MercuriusDriverConfig>({
2 driver: MercuriusDriver,
3 subscription: true,
4}),Custom emitter sozlash, kiruvchi ulanishlarni validatsiya qilish va h.k. uchun opsiyalar obyektini ham uzatishingiz mumkin. Batafsil bu yerda o'qing (subscription bo'limi).