Skip to main content

Events

The event system lets any class listen for named events published on a Redis pub/sub channel, without knowing who published them or how many other listeners exist.

Listening with @OnEvent

Decorate a method with @OnEvent(type?) to have it called whenever a matching event arrives:

import {EventDecorators} from '@rapidrest/service-core';
import type {Event} from '@rapidrest/core';
const {EventListener, OnEvent} = EventDecorators;

@EventListener()
export class PetEventHandler {
@OnEvent('pet.created')
onPetCreated(evt: Event) {
// ...
}

@OnEvent(['pet.updated', 'pet.deleted'])
onPetChanged(evt: Event) {
// ...
}

@OnEvent()
onAnyEvent(evt: Event) {
// called for every event received, regardless of type
}
}
DecoratorWhat it does
@EventListener()Class decorator. Marks a class (which must have a no-argument constructor) to be automatically instantiated and registered as an event listener at startup.
@OnEvent(type?)Method decorator. type can be a single event type, an array of types, or omitted entirely to receive every event. Types are matched as case-insensitive regular expressions, not exact strings.

As with routes and models, there's no manual registration step for a class decorated with @EventListener(). Export it anywhere under src/ and it's picked up automatically (see Auto-Discovery).

Configuring the event bus

Events flow over a Redis connection named events, and EventListenerManager subscribes to whichever channels you list under events:channels:

conf.defaults({
datastores: {
events: {type: 'redis', host: 'localhost', port: 6379},
},
events: {
channels: ['pets'],
},
});

The event system only starts if a datastore named events is configured. If it isn't, @OnEvent handlers are simply never registered, with no error.

Publishing an event

There isn't a dedicated "publish an event" helper. An event is just a JSON message with a type field, published to one of the configured channels over the same events Redis connection:

import {DatabaseDecorators} from '@rapidrest/service-core';
import type {Redis} from 'ioredis';
const {RedisConnection} = DatabaseDecorators;

export class PetService {
@RedisConnection('events')
private redis?: Redis;

async create(pet: Pet) {
const created = await this.repo.create(pet);
void this.redis?.publish('pets', JSON.stringify({type: 'pet.created', data: created}));
return created;
}
}

Any listener subscribed to the pets channel with a matching @OnEvent type receives it. The channel is just the transport; dispatch to handlers is based on the event's type field, not which channel it arrived on.