UNPKG

@sailboat-computer/event-bus

Version:

Standardized event bus for sailboat computer v3 with resilience features and offline capabilities

241 lines (204 loc) 6.92 kB
/** * Dead letter queue example * * This example demonstrates how to use the dead letter queue with the event bus. */ import { createEventBus, EventPriority, EventCategory } from '../src'; // Define the event type interface SensorReadingEvent { sensorId: string; value: number; unit: string; timestamp: string; } // Define a schema for the sensor reading event const sensorReadingSchema = { type: 'object', properties: { sensorId: { type: 'string' }, value: { type: 'number' }, unit: { type: 'string' }, timestamp: { type: 'string', format: 'date-time' } }, required: ['sensorId', 'value', 'unit', 'timestamp'], additionalProperties: false }; // Create a handler that will fail for certain sensor readings function createFailingHandler(failureCondition: (event: SensorReadingEvent) => boolean) { return (event: any) => { const sensorReading = event.data as SensorReadingEvent; console.log(`Processing sensor reading: ${sensorReading.sensorId} = ${sensorReading.value} ${sensorReading.unit}`); // Simulate a failure for certain sensor readings if (failureCondition(sensorReading)) { throw new Error(`Failed to process sensor reading: ${sensorReading.sensorId}`); } console.log(`Successfully processed sensor reading: ${sensorReading.sensorId}`); }; } async function runExample() { console.log('Starting dead letter queue example...'); // Create event bus with dead letter queue enabled const eventBus = createEventBus({ adapter: { type: 'memory', config: { serviceName: 'dlq-example' } }, offlineBuffer: { maxSize: 100, priorityRetention: true }, metrics: { enabled: true, detailedTimings: true }, deadLetterQueue: { enabled: true, maxSize: 100, maxAttempts: 3 } }); // Initialize event bus await eventBus.initialize({ adapter: { type: 'memory', config: { serviceName: 'dlq-example' } }, offlineBuffer: { maxSize: 100, priorityRetention: true }, metrics: { enabled: true, detailedTimings: true }, deadLetterQueue: { enabled: true, maxSize: 100, maxAttempts: 3 } }); // Register schema for sensor reading events eventBus.registerSchema<SensorReadingEvent>('sensor.reading.v1', sensorReadingSchema); console.log('Registered schema for sensor.reading.v1 event'); // Subscribe to sensor reading events with a handler that will fail for readings with value > 100 await eventBus.subscribe<SensorReadingEvent>( 'sensor.reading.v1', createFailingHandler(reading => reading.value > 100) ); console.log('Subscribed to sensor.reading.v1 events'); // Publish some sensor readings const readings = [ { sensorId: 'temp-cabin-main', value: 22.5, unit: '°C', timestamp: new Date().toISOString() }, { sensorId: 'pressure-engine', value: 120.0, // This will fail unit: 'psi', timestamp: new Date().toISOString() }, { sensorId: 'humidity-cabin', value: 65.0, unit: '%', timestamp: new Date().toISOString() }, { sensorId: 'temp-engine', value: 150.0, // This will fail unit: '°C', timestamp: new Date().toISOString() } ]; // Publish each reading for (const reading of readings) { try { console.log(`Publishing sensor reading: ${reading.sensorId} = ${reading.value} ${reading.unit}`); await eventBus.publish<SensorReadingEvent>( 'sensor.reading.v1', reading, { priority: EventPriority.NORMAL, category: EventCategory.DATA, tags: ['sensor', reading.sensorId] } ); console.log(`Published sensor reading: ${reading.sensorId}`); } catch (error) { console.error(`Failed to publish sensor reading: ${error.message}`); } // Wait a bit between events await new Promise(resolve => setTimeout(resolve, 100)); } // Wait for events to be processed await new Promise(resolve => setTimeout(resolve, 1000)); // Get events from the dead letter queue console.log('\nEvents in dead letter queue:'); const deadLetterEvents = await eventBus.getDeadLetterEvents(); if (deadLetterEvents.length === 0) { console.log('No events in dead letter queue'); } else { for (const event of deadLetterEvents) { console.log(`- ${event.eventType}: ${JSON.stringify(event.data)}`); console.log(` Error: ${event.error.message}`); console.log(` Attempts: ${event.attempts}`); console.log(` Timestamp: ${event.timestamp}`); } } // Get metrics const metrics = eventBus.getMetrics(); console.log('\nEvent Bus Metrics:'); console.log(`- Published events: ${metrics.publishedEvents}`); console.log(`- Failed publishes: ${metrics.failedPublishes}`); console.log(`- Processed events: ${metrics.processedEvents}`); console.log(`- Dead letter queue size: ${(metrics as any).deadLetterQueueSize}`); console.log(`- Dead letter queue events: ${(metrics as any).deadLetterQueueEvents}`); // Republish an event from the dead letter queue with a modified value if (deadLetterEvents.length > 0) { const eventToRepublish = deadLetterEvents[0]; const eventId = (eventToRepublish as any).id; console.log(`\nRepublishing event ${eventId} with modified value...`); // Modify the event data to avoid the failure condition const modifiedData = { ...eventToRepublish.data, value: 90.0 // Lower the value to avoid the failure condition }; // Republish the event const newEventId = await eventBus.publish<SensorReadingEvent>( eventToRepublish.eventType, modifiedData, { priority: EventPriority.HIGH, category: EventCategory.DATA, tags: ['republished', 'modified'] } ); console.log(`Republished event with new ID: ${newEventId}`); // Remove the event from the dead letter queue await eventBus.removeDeadLetterEvent(eventId); console.log(`Removed event ${eventId} from dead letter queue`); // Wait for the event to be processed await new Promise(resolve => setTimeout(resolve, 500)); } // Clear the dead letter queue console.log('\nClearing dead letter queue...'); await eventBus.clearDeadLetterQueue(); // Verify the dead letter queue is empty const remainingEvents = await eventBus.getDeadLetterEvents(); console.log(`Dead letter queue size after clearing: ${remainingEvents.length}`); // Close the event bus await eventBus.close(); console.log('\nDead letter queue example completed'); } // Run the example runExample().catch(error => { console.error('Example failed:', error); process.exit(1); });