Skip to content

pub/sub type safety improvements #510

Open
@cainlevy

Description

@cainlevy

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions