Подписки prisma2 возвращают данные: null

У меня есть базовая подписка pubsub, использующая шаблон и graphql-yoga: https://github.com/ryanking1809/prisma2_subscriptions https://codesandbox.io/s/github/ryanking1809/prisma2_subscriptions/tree/sql-lite

С мутацией публикации:

const Mutation = objectType({
  name: 'Mutation',
  definition(t) {
   //...
    t.field('publish', {
      type: 'Post',
      nullable: true,
      args: {
        id: idArg(),
      },
      resolve: async (parent, { id }, ctx) => {
        const post = await ctx.photon.posts.update({
          where: { id },
          data: { published: true },
          include: { author: true }
        });
        ctx.pubsub.publish("PUBLISHED_POST", {
          publishedPost: post
        });
        return post
      },
    })
  },
})

И подписка - я просто возвращаю true, чтобы убедиться, что withFilter (из graphql-yoga) работает.

const Subscription = objectType({
    name: "Subscription",
    definition(t) {
        t.field("publishedPostWithEmail", {
            type: "Post",
            args: {
                authorEmail: stringArg({ required: false })
            },
            subscribe: withFilter(
                (parent, { authorEmail }, ctx) => ctx.pubsub.asyncIterator("PUBLISHED_POST"),
                (payload, { authorEmail }) => true
            )
        });
    }
});

Возвращение следующего на publish (вы можете скопировать и вставить их в codeandbox - это здорово!)

mutation {
  publish(
    id: "cjzwz39og0000nss9b3gbzb7v"
  ) {
    id,
    title,
    author {
      email
    }
  }
}
subscription {
  publishedPostWithEmail(authorEmail:"[email protected]") {
    title,
    content,
    published
  }
}
{
  "errors": [
    {
      "message": "Cannot return null for non-nullable field Subscription.publishedPostWithEmail.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "publishedPostWithEmail"
      ]
    }
  ],
  "data": null
}

Почему-то возвращается data: null. Когда я регистрирую payload.publishedPosts в функции фильтра, кажется, что там все есть.

{ id: 'cjzwqcf2x0001q6s97m4yzqpi',
  createdAt: '2019-08-29T13:34:26.648Z',
  updatedAt: '2019-08-29T13:54:19.479Z',
  published: true,
  title: 'Check Author',
  content: 'Do you save the author?',
  author:
   { id: 'sdfsdfsdfsdf',
     email: '[email protected]',
     name: 'Prisma Sub' } }

Что-то мне не хватает?


person Ryan King    schedule 29.08.2019    source источник


Ответы (1)


Наконец-то разобрался! ????

Функция подписки должна быть названа в честь ключа в pubsub. Итак, если у вас есть функция публикации, подобная следующей:

ctx.pubsub.publish("PUBLISHED_POST", {
          publishedPost: post
        });

тогда вы должны назвать свою подписку publishedPost

        t.field("publishedPost", {
            type: "Post",
            args: {
                authorEmail: stringArg({ required: false })
            },
            subscribe: withFilter(
                (parent, { authorEmail }, ctx) =>
                    ctx.pubsub.asyncIterator("PUBLISHED_POST"),
                (payload, { authorEmail }) => payload.publishedPost.author.email === authorEmail
            )
        });

если вы назовете свою подписку publishedPostWithEmail, то данные не будут возвращены

        t.field("publishedPostWithEmail", {
                //...
        });

Интересно, если у вас 2 ключа

ctx.pubsub.publish("PUBLISHED_POST", {
          publishedPost2: post,
          publishedPost3: post
        });

Затем, если вы назовете свою подписку publishedPost2, то publishedPost3 будет исключен из результатов.


Как ни странно, если вы подписываетесь на 2 сообщения, вы получаете обратно все данные

ctx.pubsub.publish("PUBLISHED_POST", {
          publishedPost: post,
          publishedPost2: post
        });
        ctx.pubsub.publish("PUBLISHED_POST_X", {
          publishedPostX: post,
          publishedPostY: post
        });
ctx.pubsub.asyncIterator([
                        "PUBLISHED_POST",
                        "PUBLISHED_POST_X"
                    ]),

возвращает publishedPost, publishedPost2, publishedPostX, publishedPostY

Таким образом, вы можете обойти указанную выше проблему, подписавшись на массив с одним элементом, и имя подписки станет неактуальным.

        t.field("publishedPostXYZ", {
            type: "Post",
            args: {
                authorEmail: stringArg({ required: false })
            },
            subscribe: withFilter(
                (parent, { authorEmail }, ctx) =>
                    ctx.pubsub.asyncIterator([
                        "PUBLISHED_POST"
                    ]),
                (payload, { authorEmail }) => {
                    return payload.publishedPost.author.email === authorEmail;
                }
            )
        });

Похоже, это может быть ошибка ????

person Ryan King    schedule 30.08.2019