Postboy Help

IPostboyDependingService

IPostboyDependingService is an interface that solves one specific problem: preventing a service from using the bus before its message types are registered.

It also provides automatic cleanup when the parent registrator shuts down, but that is a secondary benefit.

The problem: constructor vs registration order

Services are typically instantiated via a dependency injection container. The container may create a service before the registrator that owns the messages it depends on.
If the service calls sub() or fire() on an unregistered message type, Postboy throws an error.

class AuthService { // ❌ Risky: UserLoginEvent may not be registered yet constructor(private postboy: PostboyService) { this.postboy.sub(UserLoginEvent).subscribe(/* ... */); } }

How IPostboyDependingService solves it

The interface requires a single method, up(). The service moves its subscriptions into this method instead of the constructor.

import {IPostboyDependingService, PostboyService} from '@artstesh/postboy'; class AuthService implements IPostboyDependingService { constructor(private postboy: PostboyService) { } up(): void { // Safe: the registrator guarantees all its messages are registered this.postboy.sub(UserLoginEvent).subscribe(/* ... */); } }

The parent registrator calls up() only after its own _up() has completed. At that point every recordSubject(...), recordReplay(...), etc. has been processed, so the bus is ready for subscriptions.

Registration via parent registrator

The registrator that owns the relevant message types also manages the depending services.

class AppRegistrator extends PostboyAbstractRegistrator { constructor(postboy: PostboyService, auth: AuthService) { super(postboy); // Activate the depending service — its up() will be called after _up() this.registerServices([auth]); } protected _up(): void { this.recordSubject(UserLoginEvent); } }

Execution order

registrator.up() → registrator._up() (message types registered) → authService.up() (subscriptions created) → bus ready to serve both

When registrator.down() is later called, all subscriptions from authService are cleaned up automatically.

Key benefits

  • Safe initialization — Services never observe or fire on unregistered message types.

  • No manual orchestration — The registrator determines when depending services are allowed to connect.

  • Declarative — The interface makes the dependency explicit.

  • Automatic cleanup — Subscriptions vanish with the parent registrator.

When to use IPostboyDependingService

Use it when:

  • A service subscribes to one or more messages.

  • Those messages are owned by a specific registrator.

  • The service may be created before that registrator completes its setup.

Do not use it if the service only reacts to global events that are always registered before any service is instantiated — in that case the constructor is safe enough.

Summary

IPostboyDependingService ensures that a service starts listening to the bus only after its parent registrator has finished registering all required message types. It replaces fragile constructor subscriptions with a controlled up() entry point while keeping cleanup automatic.

24 апреля 2026