Channel
π‘ Channels
In the @nestjstools/messaging
library, Channels represent the underlying transport mechanisms that deliver messages between microservices. Each channel is responsible for handling message transmission, reception, serialization, and routing to the appropriate handlers.
Channels abstract the communication details, allowing your application to work seamlessly whether using in-memory queues, RabbitMQ, or any other supported transport.
π What Is a Channel?
A Channel is a pluggable component that:
Sends and receives messages over a specific transport protocol
Applies serialization and deserialization (normalizers)
Manages queues, exchanges, topics, or other infrastructure details
Supports middleware to process messages in the pipeline
π Defining a Channel
Channels are configured within the MessagingModule via channel config classes. Each channel requires:
A unique name
Channel-specific options (connection info, queues, bindings)
Optional middlewares and normalizers
Example: InMemory Channel
import { InMemoryChannelConfig } from '@nestjstools/messaging';
new InMemoryChannelConfig({
name: 'my-channel',
middlewares: [LoggingMiddleware],
});
Example: AMQP Channel
import { MessagingRabbitmqExtensionModule, RmqChannelConfig, ExchangeType } from '@nestjstools/messaging-rabbitmq-extension';
new RmqChannelConfig({
name: 'amqp-command',
connectionUri: 'amqp://guest:guest@localhost:5672/',
exchangeName: 'my_app_command.exchange',
bindingKeys: ['my_app.command.#'],
exchangeType: ExchangeType.TOPIC,
queue: 'my_app.command',
autoCreate: true,
enableConsumer: true,
});
π§© Channel Configuration Options
name
Unique identifier of the channel
middlewares
List of middleware classes to apply on messages
normalizer
Serializer/deserializer to encode/decode messages
Transport-specific options
Connection strings, queues, exchange names, binding keys, etc.
enableConsumer
Enables or disables the RabbitMQ consumer for this channel
π Channels and Buses
A Bus is connected to one or more channels. When a message is dispatched to a bus, it is forwarded to all its associated channels.
This design allows you to:
Send messages to multiple transports simultaneously
Mix different messaging protocols within the same application
Configure channels independently for flexibility and scaling
π§© Middleware and Normalizers on Channels
Each channel can have its own middleware stack and normalizers, enabling per-transport processing and custom encoding/decoding.
π¦ Hook: onChannelDestroy
onChannelDestroy
The onChannelDestroy
The method is a lifecycle hook that is called when a channel instance is being destroyed. This is the appropriate place to clean up resources, close connections, or perform any teardown logic associated with your custom channel.
Purpose
Use onChannelDestroy
to:
Gracefully close external connections (e.g., sockets, database clients, message queues).
Dispose of timers, intervals, or event listeners.
Free up resources tied to the channelβs lifecycle.
export class ExampleChannel extends Channel<ExampleChannelConfig> {
constructor(config: ExampleChannelConfig) {
super(config);
}
async onChannelDestroy(): Promise<void> {
// Clean up logic here
// For example, close an SQS client connection
if (this.client) {
await this.client.close();
}
}
}
Notes
The method should return a
Promise<void>
.This hook is automatically called by the framework when the channel is being shut down.
Always handle errors gracefully to avoid issues during shutdown.
Benefits of Using Channels
π Transport Abstraction
Switch between RabbitMQ, in-memory, or other protocols easily
βοΈ Flexible Configuration
Fine-tune transport settings independently per channel
π§© Extensible Middleware
Add custom logic like logging, auth, or metrics per channel
π Multi-Channel Support
Dispatch messages across multiple transports simultaneously
Last updated