Event-Based Architecture
Dalam real-time systems, everything is an event. User mengetik → event. Pesan terkirim → event. User join → event. Arsitektur event-based memisahkan producer dari consumer.
Event Pattern
// Event format
interface AppEvent {
type: string; // "user:joined", "message:sent"
payload: unknown; // event-specific data
metadata: {
timestamp: number;
userId: string;
correlationId: string;
};
}
EventEmitter Pattern
import { EventEmitter } from "events";
class ChatService extends EventEmitter {
async sendMessage(userId, channelId, text) {
const message = await db.messages.create({
data: { userId, channelId, text },
});
// Emit event — decoupled dari delivery method
this.emit("message:sent", {
message,
channelId,
userId,
});
return message;
}
}
const chat = new ChatService();
// Different listeners for different concerns
chat.on("message:sent", (event) => {
// 1. Push via WebSocket
io.to(event.channelId).emit("new-message", event.message);
});
chat.on("message:sent", (event) => {
// 2. Send push notification to offline users
notificationService.notifyOffline(event.channelId, event.message);
});
chat.on("message:sent", (event) => {
// 3. Update unread count
unreadService.increment(event.channelId, event.userId);
});
Benefits
- Decoupling — Producer tidak tahu siapa consumer
- Extensibility — Tambah listener tanpa ubah producer
- Testability — Test producer dan consumer independently