Postboy Help

Broadcasting Events from Services

Services that produce data — WebSocket adapters, polling timers, background workers — are natural publishers of PostboyGenericMessage events.
They simply call fire(...) with a message instance, completely unaware of which parts of the UI (or other services) are listening.

1. WebSocket adapter publishing stock updates

The StockWebSocketAdapter receives real‑time stock data and publishes a StockUpdatedEvent whenever a product’s availability changes.

Registration happens once in the constructor.
Publishing happens inside the WebSocket message handler.

import {AppPostboyService} from '@shared/services/app-postboy.service'; import {ConnectMessage} from '@artstesh/postboy'; import {Subject} from 'rxjs'; import {StockUpdatedEvent} from './messages/events/stock-updated.event'; export class StockWebSocketAdapter { constructor(private postboy: AppPostboyService) { // Register the event type once this.postboy.exec(new ConnectMessage(StockUpdatedEvent, new Subject<StockUpdatedEvent>())); } onStockMessage(raw: { productId: string; status: string }): void { // Broadcast to every interested subscriber this.postboy.fire(new StockUpdatedEvent(raw.productId, raw.status)); } }

2. Customer queue adapter broadcasting queue changes

A different service, CustomerQueueWebSocketAdapter, publishes CustomerQueueEvent when the number of waiting customers changes.

import {AppPostboyService} from '@shared/services/app-postboy.service'; import {ConnectMessage} from '@artstesh/postboy'; import {Subject} from 'rxjs'; import {CustomerQueueEvent} from './messages/events/customer-queue.event'; export class CustomerQueueWebSocketAdapter { constructor(private postboy: AppPostboyService) { this.postboy.exec(new ConnectMessage(CustomerQueueEvent, new Subject<CustomerQueueEvent>())); } onQueueUpdate(count: number): void { this.postboy.fire(new CustomerQueueEvent(count)); } }

3. Subscribing in components (the other side)

Components interested in these events subscribe without importing the adapter service.
They only depend on the message class and the bus.

Header component — listens to both events and displays counts.

import {AppPostboyService} from '@shared/services/app-postboy.service'; import {StockUpdatedEvent} from './messages/events/stock-updated.event'; import {CustomerQueueEvent} from './messages/events/customer-queue.event'; export class OperatorHeaderComponent { queueCount = 0; availableItems = 0; constructor(private postboy: AppPostboyService) { this.postboy.sub(CustomerQueueEvent).subscribe((msg) => { this.queueCount = msg.count; }); this.postboy.sub(StockUpdatedEvent).subscribe((msg) => { // Some logic to calculate available items from update events if (msg.newStatus === 'Available') this.availableItems++; else this.availableItems--; }); } }

Toast notification service — shows a popup for each stock change.

export class NotificationService { constructor(private postboy: AppPostboyService) { this.postboy.sub(StockUpdatedEvent).subscribe((msg) => { this.showToast(`Product ${msg.productId} is now ${msg.newStatus}`); }); } }

Key points

  • A service becomes a publisher by calling fire(...) — no knowledge of subscribers is needed.

  • The same event type can be consumed by multiple components or services in completely different ways.

  • Adding a new listener (e.g., a logging service) requires no change in the publishing service.

  • All communication remains typed and explicit via the message class.

03 мая 2026