Skip to content

Using an external PubSub engine #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
emmanuelvacher opened this issue Jun 6, 2017 · 4 comments
Closed

Using an external PubSub engine #70

emmanuelvacher opened this issue Jun 6, 2017 · 4 comments
Labels

Comments

@emmanuelvacher
Copy link

emmanuelvacher commented Jun 6, 2017

Hello,

I would like to know if it is possible to use graphql-mqtt-subscriptions along with this package. More precisely, I'd like someone to explain how to wrap a pubsub with an AsyncIterator since the apollo client needs one for the subscription to be effective.

My final goal is to use a MQTT broker to handle subscriptions instead of the in-memory pubsub engine provided by your package.

Thank you for your help.

@dotansimha
Copy link
Contributor

dotansimha commented Jun 6, 2017

@emmanuelvacher

Basically, you can implement any custom PubSub, the only thing that is important is to return AsyncIterator as your subscription stream.

You can implement your own logic and transform your MQTT subscription into an AsyncIterator and use it as your subscriptions stream.

AsyncIterator API should implement the AsyncIterator Symbol, next, return and throw methods.
This is an example for a simple AsyncIterator creator, that maps Redis subscriptions into an AsyncIterator (haven't tested it, but it should work 😆 ):

import { $$asyncIterator } from 'iterall';

const redisClient = createClient({ host, port, password });

const redisEventToAsyncIterator = (redisClient: RedisClient, eventName: string) => {
  let promiseResolve;

  redisClient.on('message', (channel: string, message: string) => {
    const parsedMessage = JSON.parse(message);

    if (promiseResolve && eventName === channel) {
      promiseResolve(parsedMessage);
    }
  });

  return {
    next() {
      return new Promise(resolve => {
        promiseResolve = resolve;
      }).then(value => ({
        done: false,
        value,
      }));
    },
    return() {
      return Promise.resolve({ done: true, value: undefined });
    },
    throw(e: Error) {
      return Promise.reject(e);
    },
    [$$asyncIterator]() {
      return this;
    },
  };
};

Then, you can use it as your subscriptions stream, in your resolver:

const REDIS_EVENT_NAME = 'something_changed';

const resolvers = {
   Subscription: {
        somethingChanged: {
             subscribe: () => redisEventToAsyncIterator(client, REDIS_EVENT_NAME),
        }
   }
}

And then each time your Redis instance publishes a message - it will map this message to your GraphQL subscription.

You can see more implementations of AsyncIterator here:

The graphql-mqtt-subscriptions and graphql-redis-subscriptions uses the old API of subscriptions, and it needs an update (@davidyaha), but you can simply implement it now with a custom AsyncIterator.

@emmanuelvacher
Copy link
Author

@dotansimha Thank you very much, I'm going to try that.

@dotansimha
Copy link
Contributor

@emmanuelvacher did you managed to implement your own AsyncIterator? can we close this issue?

@emmanuelvacher
Copy link
Author

@dotansimha yes I managed to implement my own AsyncIterator thanks to your advice 👍 you can close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants