@logistically/events-nestjs
v2.0.1
Published
NestJS integration for @logistically/events v3 - Event-driven architecture with Redis Streams
Maintainers
Readme
@logistically/events-nestjs
A NestJS integration library for the @logistically/events event system, providing integration with NestJS applications including automatic event handler discovery, decorators, and services.
Features
- NestJS Integration - Designed for NestJS with decorators and dependency injection
- Automatic Event Handler Discovery - Automatically discovers and registers event handlers using decorators
- Performance Optimizations - Intelligent caching, batch processing, and performance monitoring
- Multiple Transport Support - Redis Streams, Memory, and custom transport plugins
- Pattern-Based Event Routing - Flexible event routing with wildcard support
- Type Safety - Full TypeScript support with proper typing
- Minimal Configuration - Minimal setup required with sensible defaults
- Global Module Support - Can be configured as a global module for app-wide access
Installation
npm install @logistically/events-nestjs @logistically/eventsQuick Start
1. Import the Module
import { Module } from '@nestjs/common';
import { EventsModule } from '@logistically/events-nestjs';
@Module({
imports: [
EventsModule.forRoot({
service: 'my-app',
autoDiscovery: true,
global: true
})
]
})
export class AppModule {}2. Create Event Handlers
import { Injectable } from '@nestjs/common';
import { AutoEvents, AutoEventHandler, NestJSEvent } from '@logistically/events-nestjs';
@Injectable()
@AutoEvents()
export class UserService {
@AutoEventHandler({ eventType: 'user.created' })
async handleUserCreated(event: NestJSEvent<{ id: number; email: string }>) {
console.log('User created:', event.body);
}
@AutoEventHandler({ eventType: 'order.*' })
async handleAllOrderEvents(event: NestJSEvent<any>) {
console.log('Order event received:', event.body);
}
}3. Publish Events
import { Injectable } from '@nestjs/common';
import { EventPublisherService } from '@logistically/events-nestjs';
@Injectable()
export class OrderService {
constructor(private readonly eventPublisher: EventPublisherService) {}
async createOrder(orderData: any) {
// Your business logic here
// Publish event
await this.eventPublisher.publish('order.created', orderData);
}
}That's it! Your event handlers will be automatically discovered and registered.
Core Concepts
Event System
This library integrates with the @logistically/events core library, which provides:
- Event Publishing - Publish events to multiple transports
- Event Consumption - Consume events with pattern matching
- Transport Plugins - Redis Streams, Memory, and custom transports
- Event Routing - Pattern-based routing between transports
- Batching & Performance - Configurable batching strategies
- Reliability - Dead letter queues, retries, and error handling
For detailed information about the core event system, see @logistically/events.
NestJS Integration
The library provides NestJS-specific features:
- Module Integration -
EventsModulefor easy setup - Service Injection - Injectable services for publishing and consuming
- Decorator Support - Decorators for automatic handler registration
- Dependency Injection - Full NestJS DI integration
- Lifecycle Hooks - Integration with NestJS lifecycle
Configuration
Basic Configuration
EventsModule.forRoot({
service: 'my-app', // Service name for event routing
originPrefix: 'my-app', // Origin prefix for events
autoDiscovery: true, // Enable automatic handler discovery
global: true // Make module globally available
})Advanced Configuration
import { RedisStreamsPlugin, MemoryTransportPlugin } from '@logistically/events';
EventsModule.forRoot({
service: 'my-app',
originPrefix: 'my-app',
autoDiscovery: true,
global: true,
// Transport configuration
transports: new Map([
['redis', new RedisStreamsPlugin().createTransport({
url: 'redis://localhost:6379',
groupId: 'my-app-group'
})],
['memory', new MemoryTransportPlugin().createTransport()]
]),
// Event routing
routing: {
routes: [
{ pattern: 'user.*', transport: 'redis' },
{ pattern: 'order.*', transport: 'redis' },
{ pattern: 'system.*', transport: 'memory' }
]
},
// Publisher configuration
publisher: {
batching: {
enabled: true,
maxSize: 1000,
maxWaitMs: 100
}
},
// Consumer configuration
consumer: {
enablePatternRouting: true,
enableConsumerGroups: true
}
})For complete configuration options, see @logistically/events Configuration.
API Reference
Decorators
@AutoEvents(options?)
Simple decorator for automatic event handler discovery.
@AutoEvents({ enabled: true, priority: 0 })
export class MyService {}Options:
enabled(boolean): Enable/disable auto-discovery for this servicepriority(number): Priority for handler registration order
@AutoEventHandler(options)
Marks a method as an event handler.
@AutoEventHandler({ eventType: 'user.created' })
async handleUserCreated(event: NestJSEvent<User>) {
// Handle event
}Options:
eventType(string): Event type pattern (supports wildcards likeuser.*)priority(number): Handler priority within the same event typeasync(boolean): Whether the handler is asyncretry(object): Retry configuration
Services
EventPublisherService
Publishes events to the event system.
constructor(private readonly eventPublisher: EventPublisherService) {}
// Publish single event
await this.eventPublisher.publish('user.created', userData);
// Publish batch
await this.eventPublisher.publishBatch('user.created', users);EventConsumerService
Consumes events from the event system.
constructor(private readonly eventConsumer: EventConsumerService) {}
// Subscribe to specific event
await this.eventConsumer.subscribe('user.created', handler);
// Subscribe to pattern
await this.eventConsumer.subscribePattern('user.*', handler);EventSystemService
Manages the core event system.
constructor(private readonly eventSystem: EventSystemService) {}
// Get system status
const status = await this.eventSystem.getStatus();
// Check connection
const connected = this.eventSystem.isConnected();EventDiscoveryService
Manages automatic event handler discovery and registration.
constructor(private readonly eventDiscoveryService: EventDiscoveryService) {}
// Manual registration
const count = await this.eventDiscoveryService.registerEventHandlers(this);Event Object
NestJSEvent<T>
The event object passed to handlers. This extends the core EventEnvelope<T> from @logistically/events.
interface NestJSEvent<T = any> extends EventEnvelope<T> {
nestjsMetadata?: NestJSEventMetadata;
}
interface NestJSEventMetadata {
correlationId?: string;
causationId?: string;
[key: string]: any;
}The event object inherits all properties from EventEnvelope<T> which includes:
body: T- The event payload dataheader- Event metadata (id, type, origin, timestamp, etc.)nestjsMetadata- Optional NestJS-specific metadata
Transport Plugins
Redis Streams
import { RedisStreamsPlugin } from '@logistically/events';
const redisTransport = new RedisStreamsPlugin().createTransport({
url: 'redis://localhost:6379',
groupId: 'my-app-group',
batchSize: 100,
enableDLQ: true,
maxRetries: 3
});Memory Transport
import { MemoryTransportPlugin } from '@logistically/events';
const memoryTransport = new MemoryTransportPlugin().createTransport();For complete transport configuration options, see @logistically/events Transports.
Event Routing
Pattern-Based Routing
routing: {
routes: [
{ pattern: 'user.*', transport: 'redis' }, // All user events to Redis
{ pattern: 'order.created', transport: 'redis' }, // Specific event to Redis
{ pattern: 'system.*', transport: 'memory' } // System events to memory
]
}Wildcard Support
user.*- All user eventsorder.*.created- Order events ending with 'created'*.notification- All notification events
For advanced routing configuration, see @logistically/events Routing.
Error Handling
Handler Error Handling
@AutoEventHandler({ eventType: 'user.created' })
async handleUserCreated(event: NestJSEvent<User>) {
try {
// Your logic here
} catch (error) {
// Handle errors - they won't break the event system
console.error('Handler error:', error);
}
}Dead Letter Queue (Redis)
const redisTransport = new RedisStreamsPlugin().createTransport({
enableDLQ: true,
dlqStreamPrefix: 'dlq:',
maxRetries: 3
});For comprehensive error handling strategies, see @logistically/events Error Handling.
Testing
Unit Testing
import { Test } from '@nestjs/testing';
import { EventsModule } from '@logistically/events-nestjs';
describe('UserService', () => {
let service: UserService;
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [
EventsModule.forRoot({
service: 'test',
autoDiscovery: true
})
],
providers: [UserService]
}).compile();
service = module.get<UserService>(UserService);
});
it('should handle user created events', async () => {
// Test your event handler
});
});Integration Testing
import { Test } from '@nestjs/testing';
import { EventsModule } from '@logistically/events-nestjs';
describe('Event Integration', () => {
let app: INestApplication;
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [
EventsModule.forRoot({
service: 'test',
autoDiscovery: true,
transports: new Map([
['memory', new MemoryTransportPlugin().createTransport()]
])
})
]
}).compile();
app = module.createNestApplication();
await app.init();
});
afterEach(async () => {
await app.close();
});
});Troubleshooting
Common Issues
Handlers Not Being Registered
- Ensure
autoDiscovery: trueis set in module configuration - Verify the service has the
@AutoEvents()decorator - Check that
EventDiscoveryServiceis injected into the service - Verify event handler methods have the
@AutoEventHandler()decorator
Events Not Being Received
- Check transport configuration
- Verify event routing patterns
- Ensure consumer is properly initialized
- Check Redis connection (if using Redis transport)
Debug Mode
Enable debug logging:
EventsModule.forRoot({
service: 'my-app',
autoDiscovery: true,
debug: true // Enable debug logging
})Examples
See the examples/ directory for complete working examples:
- Basic Setup - Simple event handler registration
- Cross-Service Communication - Services handling events from other services
- Pattern-Based Routing - Event routing between transports
- Redis Integration - Production-ready Redis Streams setup
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License
MIT License - see LICENSE file for details.
Related Links
- @logistically/events - Core events library with detailed configuration, features, and benchmarks
- NestJS - Progressive Node.js framework
- Redis - In-memory data structure store
