graphql-redis-subscriptions icon indicating copy to clipboard operation
graphql-redis-subscriptions copied to clipboard

pub/sub type safety improvements

Open cainlevy opened this issue 2 years ago • 0 comments

I'm working to improve the type safety of our RedisPubSub integration and have found a simple pattern that I believe may be useful to other people.

Problem

The distance between publishing and subscribing/consuming makes it easy to introduce typos and mismatched payloads.

Workaround

Define a list of trigger names with associated payload types:

type TriggeredPayloads = {
  helloWorld: string;
};

type TypedRedisPubSub = RedisPubSub & {
  publish: <T extends keyof TriggeredPayloads>(
    topic: T,
    payload: TriggeredPayloads[T],
  ) => Promise<void>;
  asyncIterator: <T extends keyof TriggeredPayloads>(topic: T) => AsyncIterator<T>;
};

const myPubSub = new RedisPubSub() as TypedRedisPubSub;

// ok
myPubSub.publish('helloWorld', 'Bonjour');
// not ok
myPubSub.publish('helloworld', 'Bonjour');
myPubSub.publish('helloWorld', true);

// ok
myPubSub.asyncIterator('helloWorld');
// not ok
myPubSub.asyncIterator('helloworld');

Feature Request

It would be nice if the RedisPubSub constructor accepted a generic containing a record of supported triggers and payloads:

type TriggeredPayloads = {
  helloWorld: string;
};
const myPubSub = new RedisPubSub<TriggeredPayloads>();

The optimalbits/bull library has a similar problem (message passing between job producers & workers) and also implements a solution like this.

Caveats

  • This only helps codebases that contain both the publisher and the subscriber
  • This does not solve race conditions during a deploy where the new version includes payload changes

cainlevy avatar Apr 13 '22 16:04 cainlevy