Publishing and subscribing with Redis

Redis has a built-in pub/sub mechanism. Publishers send messages to a channel. Subscribers listen on the channel and receive every message. It is fire-and-forget: if nobody is subscribed when the message is published, the message is gone.

order-service/events/publisher.ts
typescript
import { Redis } from 'ioredis';

let _publisher: Redis | null = null;

function getEventPublisher(): Redis {
  if (!_publisher) _publisher = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
  return _publisher;
}

export async function publishDomainEvent(eventName: string, payload: unknown) {
  try {
    await getEventPublisher().publish(eventName, JSON.stringify(payload));
  } catch (err) {
    console.warn('Could not publish ' + eventName + ': ' + (err as Error).message);
  }
}

The order service publishes a domain event with a small payload.

inventory-service/events/subscriber.ts
typescript
import { Redis } from 'ioredis';
import { db } from '../db';
import { inventory } from '../db/schema';
import { eq, sql } from 'drizzle-orm';

// IMPORTANT: subscriber connections cannot run normal commands.
// Always use a dedicated connection for subscribing.
const subscriber = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');

export function setupEventSubscriptions() {
  subscriber.subscribe('OrderPlaced');

  subscriber.on('message', async (channel, message) => {
    if (channel !== 'OrderPlaced') return;
    const payload = JSON.parse(message);

    await db
      .update(inventory)
      .set({ stockQuantity: sql`stock_quantity - ${payload.quantity}` })
      .where(eq(inventory.bookId, payload.bookId));

    console.log('Inventory updated for book ' + payload.bookId);
  });
}

The inventory service subscribes to OrderPlaced and deducts stock.

One Redis quirk worth remembering. A connection that is subscribed to a channel cannot run normal commands like GET or SET. Redis switches the connection into subscriber mode and refuses everything else. Always use a dedicated connection for subscribing. Keep another for publishing and regular reads.

Quiz: Quiz

Loading practiceโ€ฆ