little-bear-labs / aws-utils

Apache License 2.0
56 stars 35 forks source link

Mutation triggers subscription resolver #98

Open JimmyHurrah opened 5 years ago

JimmyHurrah commented 5 years ago

When running a mutation that has a subscription it seems to trigger the subscription resolver, I'm under the impression that the subscription resolver should only be triggered on the initial subscription registration and that the data published to the subscription should be the return payload of the mutation.

From the appsync devguide "Subscriptions are triggered from mutations and the mutation selection set is sent to subscribers." ... "Although the subscription query is needed for client connections and tooling, the selection set that is received by subscribers is specified by the client triggering the mutation."

I use a resolver to authorize subscriptions as described in the security section of the devguide response mapping returns null to continue or $utils.unauthorized() to fail.

It seems the emulator is using the resolver mapping for the subscription on the data, which in my case results in the published data to be null

My code works fine in appsync but not in the emulator, Any thoughts on this?

cbaron commented 5 years ago

@JimmyHurrah -- I suspect you've found a bug in the emulator. If I understand you correctly, the following needs to be changed:

1) subscription resolver should always return the payload of the mutation

Could you explain in a little more detail, or provide code examples regarding the triggering of the subscription resolver?

As I understand things, its okay if the subscription resolver is triggered, it only matters that clients subscribing to these resolvers can receive the data after initiating a subscription via web socket.

JimmyHurrah commented 5 years ago

@cbaron Your understanding of the problem is spot on. It does not really matter if the resolver is triggered as long as the response is from the mutation.

I guess the easiest way to reproduce this would be to have a mutation with a subscription where the subscription response mapping always returns null

Maybe a log from when I trigger a mutation will help. I have a subscription called onMessage which subscribes to a mutation createMessage where the request mapping for the subscription only returns null Heres the output from sending the mutation:

● start graphql
  mutation createMessage($conversationid: ID!, $text: String!) {
    createMessage(conversationid: $conversationid, text: $text) {
      _id
      text
      __typename
    }
  }
● start Resolve: Mutation.createMessage [createMessage]
ℹ info Rendered Request:
  { version: '2017-02-28',
    operation: 'Invoke',
    payload:
     { type: 'Mutation',
       field: 'createMessage',
       args: { conversationid: '1', text: 'Test' },
       source: {},
    } }
ℹ info Dispatch to source { name: 'Resolvers', type: 'AWS_LAMBDA' }
Received payload {} {"type":"Mutation","field":"createMessage","args":{"conversationid":"1","text":"Test"},"source":{}}
ℹ info Rendered Response:
  { conversationid: '1',
    author: '1',
    createdAt: '2019-03-10T21:56:45.603Z',
    text: 'Test',
    _id: '1' }
● start Resolve: Subscription.onMessage [onMessage]
ℹ info Dispatch to source { name: 'Resolvers', type: 'AWS_LAMBDA' }
Received payload {} {"type":"Subscription","field":"onMessage","args":{"conversationid":"1","author":"1","createdAt":"2019-03-10T21:5
ℹ info Rendered Request: { authorized: true }
ℹ info Rendered Response: null
ℹ info publish
  { payload: { data: { onMessage: null } },
    clientId: '1234567890',
    topicId: '88f5b85f-7a40-491b-80d5-c0d3023de867' }
ℹ info client (1234567890) unsubscribed to : 88f5b85f-7a40-491b-80d5-c0d3023de867
ℹ info client disconnected to subscription server (1234567890)
cbaron commented 5 years ago

Got it. That shouldn't be too hard to fix in the emulator. I will try to get to it this week. As always, you're welcome to put up a PR as well -- let me know if I can be of assistance.

Also, in the meantime, I think as a workaround you can follow the example laid out in in our unit tests.

Here is the serverless.yml which uses a "pass through" subscription resolver to return exactly the mutation:

        dataSource: SubscriberPassthrough
        type: Subscription
        field: subscribeToPutQuoteRequest
        request: subscribePassthrough-request.txt
        response: result-response.txt
JimmyHurrah commented 5 years ago

I tried looking into the subscription code before opening this issue but I couldn't really follow how the pubsub, mqtt and subscription server stuff worked together. I might give it another go later this week.

Thanks for the workaround, it works as expected 👍