34.Subscription(2)_pubsub_subscribe

김종민·2022년 4월 29일
0

insta-backend

목록 보기
35/37

wsServer는 위에서 server.js에서 setUp을 마쳤고, 이제 resolver에서 실제로 구현을 해 봄!!

https://www.apollographql.com/docs/apollo-server/data/subscriptions/

1. pubsub.js

npm install graphql-subscriptions

import { PubSub } from 'graphql-subscriptions'

const pubsub = new PubSub()

export default pubsub

prism처럼 root자리에 pubsub.js를 만들어 아무 subscribe resolver에서 가져다 쓸 수 있게 함.

2. messages/roomUpdates/roomUpdates.tyypeDefs.js

Subscribe하는 부분, 채팅에서 상대방이 보낸 톡들이 계속 찍힘.

import { gql } from "apollo-server";

export default gql`
    type Subscription {
        roomUpdates(id:Int!): Message
    }
`

3. constants.js

root에 constant.js 파일만듬,

export const NEW_MESSAGE = 'NEW_MESSAGE'

publish와 subscribe를 연결해 주는 key같은 것임.

4. messages/roomUpdates/roomUpdates.resolvers.js

Subscribe하는 부분, 채팅에서 상대방이 보낸 톡들이 계속 찍힘.
이거보다 간단하게 만들 수 있지만, 이중, 삼중으로 방어막 만들어놓음.

import { NEW_MESSAGE } from '../../constants'
import pubsub from '../../pubsub'
import { withFilter } from 'graphql-subscriptions'
import prisma from '../../client'

//import에 NEW_MESSAGE, pubsub, withFilter확인할 것

export default {
  Subscription: {
  ///Mutation 및 Query가 들어가는 자리에 Subscription이 들어감.
  
    roomUpdates: {
      subscribe: async (root, args, context, info) => {
      //async전에 subscribe를 적어줌.
      //arg는 메세지를 실시간으로 받을 roomId 임.
      //console.log로 context를 찍어보면, server에서 보낸 loggedInUser가 보임.
      
        console.log(context.id)
        const room = await prisma.room.findFirst({
          where: {
            id: args.id,
            users: {
              some: {
                id: context.id,
              },
            },
          },
          select: { id: true },
        })
        if (!room) {
          throw new Error('You shall not see this.')
        }
        ///args와 context를 이용해서 메세지를 실시간으로 받을 room을 찾음.
        ///room의 id만 select함.
        
        ///withFilter를 통해서 subscribe할 조건 및 내용을 만들어줌.
        return withFilter(
          () => pubsub.asyncIterator(NEW_MESSAGE),
          //NEW_MESSAGE key를 넣어줌.
          
          
          //   (payload, variables) => {
          //     return payload.roomUpdates.roomId === variables.id
          //   }
          //withFilter는 payload, variables 2개의 인자를 받는데
          //console로 위 두개를 찍어보면 뭘 받는지 보임.
          //밑에서 구현함..
          
          async ({ roomUpdates }, { id }, context) => {
          ///payload부분에 roomUpdates를 넣어줌,
          ///roomUpdates는 sendMessage.resolver의 publish부분에서 오는data임
          /// id는 roomUpdate의 arg(즉, 메세지 받을 방 id)
          /// context는 server.js 에서 보낸 loggedInUser 정보임.
          
            if (roomUpdates.roomId === id) {
            //loggedIn User가 방에 있는지
            //publish의 roomId와 subscribe의 roomId가 같은지
            //디시 한번 더 check해줌
            
              const room = await prisma.room.findFirst({
                where: {
                  id,
                  users: {
                    some: {
                      id: context.id,
                    },
                  },
                },
                select: {
                  id: true,
                },
              })
              if (!room) {
                return false
              }
              return true
              
              //로직이 끝나고 마지막에 꼭 return true 해줄것!!
            }
          }
        )(root, args, context, info)
        
        //callback Fn이기 떄문에 withFilter()끝나는 부분에
        //(root, args, context, info)꼭 넣어 주어야 함.
      },
    },
  },
}

--------------------------------------------------------
// export default {
//   Subscription: {
//     roomUpdates: {
//       subscribe: withFilter(
//         () => pubsub.asyncIterator(NEW_MESSAGE),
//         (payload, variables) => {
//           //   console.log(payload, variables)
//           return payload.roomUpdates.roomId === variables.id

//         }
//       ),
//     },
//   },
// }
~~~~~~~~~~~~~~~~~~~~~~간단하게 subscribe를 구현해 본 code임. 참고하삼!!!
profile
코딩하는초딩쌤

0개의 댓글