aws-lambda-graphql: [LocalStack] - GraphQL Playground is not able to run subscription

I am trying this library and so far its all good for Queries and Mutation. However the real reason I am trying this library is to work with GraphQL subscription in Serverless.

So after running this server, If i try to connect via google console a raw ws connection var socket = new WebSocket("ws://localhost:3001");, It saves a record in DynamoDB Connections table.

However, from GraphQL playground, running the subscription, it goes to listening mode forever, but there is no effect on the server.

Please advise.

Thanks

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 26 (15 by maintainers)

Most upvoted comments

@IslamWahid I added the code you proposed to the server example.

I don’t have any experience with localstack but you already know that your stream is not listening to events from dynamodb because that is something that is handled by https://github.com/michalkvasnicak/aws-lambda-graphql/blob/master/packages/chat-example-server/serverless.yml#L11

So you need to find a way how to listen to those changes and call the event handler for event processor. That’s not something that is a part of this library because in AWS DynamoDB Stream is responsible for calling your Lambda function. In local environment you need an intermediary mechanism that will connect to a stream and call your handler.

Hi @michalkvasnicak

Thanks for your reply.

I was trying to dig in the code and found two things that I need to do.

1 - In order to use GraphQL playground that comes with ApolloServer, we need to tell the websocket URL explicitly

const server = new Server({
	connectionManager,
	eventProcessor: new DynamoDBEventProcessor(),
	resolvers,
	subscriptionManager,
	typeDefs,
	dataSources,
	context: {
		pubsub
	},
	playground: {
		subscriptionEndpoint: "ws://localhost:3001"
	}
});

After doing this, If i run subscription via PlayGround, it connects fine.

2 - Second in file DynamoDBConnectionManager.js the this.hydrateConnection method was failing because it was trying to read record from Connections table and returning empty {}. I think its a race condition somehow. I explicitly set the retryCount variable to 5 and it worked until here.

Now my situation is that I can subscribe to the server, my PlayGround is in listening mode, The records are created in Connections, Subscriptions, SubscriptionOperations table which seems all good. However, upon mutation, my subscription client is still on listening mode. If I check Events table, there is a published event present which I published in my mutation function.

Can you see what could potentially be wrong here.?

Thanks alot for helping.

Hi @michalkvasnicak

Thanks for your reply. Let me try to explain you steps.

My server is running as per the documentation in this repository.

Serverless: Offline [HTTP] listening on http://localhost:3000
Serverless: Offline [websocket] listening on ws://localhost:3001

My serverless.yml looks like

functions:
  httpHandler:
    handler: graphql.handleHTTP
    events:
      - http:
          path: /
          method: any
          cors: true
  wsHandler:
    handler: graphql.handleWebSocket
    events:
      - websocket:
          route: $connect
      - websocket:
          route: $disconnect
      - websocket:
          route: $default
  eventProcessorHandler:
    handler: graphql.handleEvents
    events:
      - stream:
          enabled: true
          type: dynamodb
          arn:
            Fn::GetAtt: [EventsDynamoDBTable, StreamArn]

If i open GraphQL playground at http://localhost:3000, I can successfully speak with the server and do queries and mutations. In my mutation I am also publishing and I can verify this in the DynamoDB Events table which class DynamoDBEventStore uses.

export const createSomething = async (
	_: any,
	{ foo, bar }: FooBar,
	{
		dataSources,
		pubsub
	}: { dataSources: { baz: BazApi }; pubsub: PubSub }
) => {
	const response = await dataSources.baz.createSomething(
		foo as Foo,
		bar as Bar
	);

	await pubsub.publish(SOMETHING_CREATED, response);

	return response;
};

The problem is if i open GraphQL Playground in two browsers, Run subscription in one browser so that it goes to listening… mode and run mutation in the other browser.

My expectation is that the Connections, Subscriptions and SubscriptionOperations table in Dynamodb should be populated by this time with a record based on one client is on listening mode.

However, that listening mode stays as it is forever. However, I see one record populated in the Events table.

Please let me know if you have more questions. I know I am not able to put properly into words the problem.