4.7 KiB
4.7 KiB
Event-Driven Architecture Migration Guide
Date: 2025-01-27 Purpose: Guide for migrating projects to event-driven architecture Status: Complete
Overview
This guide provides instructions for migrating projects to use the shared event bus (NATS) for event-driven communication.
Prerequisites
- NATS event bus deployed
- Access to event bus
- Understanding of event-driven patterns
Migration Steps
Step 1: Install NATS Client
pnpm add nats
Step 2: Create Event Publisher
import { connect, NatsConnection } from 'nats';
class EventPublisher {
private nc: NatsConnection | null = null;
async connect() {
this.nc = await connect({
servers: process.env.NATS_URL || 'nats://nats:4222',
});
}
async publish(subject: string, data: unknown) {
if (!this.nc) {
await this.connect();
}
await this.nc!.publish(subject, JSON.stringify(data));
}
async close() {
await this.nc?.close();
}
}
Step 3: Create Event Subscriber
import { connect, NatsConnection } from 'nats';
class EventSubscriber {
private nc: NatsConnection | null = null;
async connect() {
this.nc = await connect({
servers: process.env.NATS_URL || 'nats://nats:4222',
});
}
async subscribe(subject: string, handler: (data: unknown) => void) {
if (!this.nc) {
await this.connect();
}
const sub = this.nc!.subscribe(subject);
for await (const msg of sub) {
const data = JSON.parse(msg.data.toString());
handler(data);
}
}
async close() {
await this.nc?.close();
}
}
Step 4: Define Event Schemas
// events/user-events.ts
export interface UserCreatedEvent {
type: 'user.created';
userId: string;
email: string;
timestamp: Date;
}
export interface UserUpdatedEvent {
type: 'user.updated';
userId: string;
changes: Record<string, unknown>;
timestamp: Date;
}
Step 5: Publish Events
import { EventPublisher } from './event-publisher';
import { UserCreatedEvent } from './events/user-events';
const publisher = new EventPublisher();
async function createUser(userData: UserData) {
// Create user logic
const user = await createUserInDB(userData);
// Publish event
const event: UserCreatedEvent = {
type: 'user.created',
userId: user.id,
email: user.email,
timestamp: new Date(),
};
await publisher.publish('events.user.created', event);
}
Step 6: Subscribe to Events
import { EventSubscriber } from './event-subscriber';
import { UserCreatedEvent } from './events/user-events';
const subscriber = new EventSubscriber();
async function setupEventHandlers() {
await subscriber.subscribe('events.user.created', async (data: UserCreatedEvent) => {
// Handle user created event
await sendWelcomeEmail(data.email);
await createUserProfile(data.userId);
});
}
Best Practices
Event Naming
- Use consistent naming:
events.{domain}.{action} - Examples:
events.user.created,events.order.placed
Event Schema
- Define schemas using TypeScript interfaces
- Include type, timestamp, and relevant data
- Version events for compatibility
Error Handling
- Implement retry logic
- Use dead letter queues
- Log all events
Monitoring
- Track event rates
- Monitor latency
- Set up alerts
Testing
Unit Tests
import { describe, it, expect } from 'vitest';
import { EventPublisher } from './event-publisher';
describe('EventPublisher', () => {
it('should publish events', async () => {
const publisher = new EventPublisher();
await publisher.publish('test.event', { data: 'test' });
// Verify event was published
});
});
Integration Tests
import { describe, it, expect } from 'vitest';
import { EventPublisher, EventSubscriber } from './events';
describe('Event Integration', () => {
it('should publish and receive events', async () => {
const publisher = new EventPublisher();
const subscriber = new EventSubscriber();
const received: unknown[] = [];
await subscriber.subscribe('test.event', (data) => {
received.push(data);
});
await publisher.publish('test.event', { data: 'test' });
await new Promise(resolve => setTimeout(resolve, 100));
expect(received).toHaveLength(1);
});
});
Migration Checklist
- Install NATS client
- Create event publisher
- Create event subscriber
- Define event schemas
- Update code to publish events
- Update code to subscribe to events
- Test event publishing
- Test event subscription
- Set up monitoring
- Update documentation
Last Updated: 2025-01-27