Concepts & Overview
Every subscription created through Postboy (sub(...), recordSubject(...), etc.) holds a reference that must be released when the owning component, service, or module is destroyed.
Without a systematic strategy, manual unsubscribe leads to memory leaks and scattered cleanup logic.
Postboy offers three mechanisms to manage the lifecycle of subscriptions, each suited for a different granularity.
1. The problem: manual lifecycle control
When you call postboy.sub(Message), you receive a Subscription. You must keep it and call unsubscribe() at the appropriate time.
In a real application this becomes fragile — missing a single unsubscribe can cause memory leaks or duplicate reactions.
2. Three scoping mechanisms
2.1 Registrators (PostboyAbstractRegistrator)
A registrator groups message registrations and subscriptions into a single class with an explicit up()/down() lifecycle.
Best for: global or feature‑level scopes where many messages are involved and you want centralised lifecycle control.
2.2 Namespaces
A namespace is a string‑scoped group of message types. Adding a namespace and recording subjects automatically ties subscriptions to that scope. Eliminating the namespace unsubscribes everything under it.
Best for: scoped logic inside a single component or service; lighter than creating a full registrator.
2.3 IPostboyDependingService
Services that implement IPostboyDependingService define their subscriptions inside an up() method. A parent registrator calls registerServices([…]) to activate them and automatically cleans them up on down().
Services that implement IPostboyDependingService defer their subscription setup to an up() method. A parent registrator invokes this method only after all message types it owns have been registered, preventing errors caused by premature access to the bus.
Best for: delegating lifecycle responsibility from a feature module to individual services, while keeping overall cleanup in one place.
3. Choosing the right mechanism
Mechanism | Granularity | Cleanup trigger | Boilerplate |
|---|---|---|---|
Registrator | Module / global |
| Medium |
Namespace | Component / service |
| Low |
Depending service | Service (via registrator) |
| Low |
Use a registrator when you need to manage many message types for a whole feature.
Use a namespace when only a few messages live inside a single class.
Use a depending service when a service’s logic belongs to a broader registrator and you want automatic cleanup without calling
EliminateNamespacemanually.
4. Key principle
No matter which mechanism you choose, Postboy guarantees that all subscriptions created within a scope are released when that scope ends — no manual unsubscribe() calls required.