Files
michaelschiemer/docs/modules/event-bus.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

7.7 KiB

Event Bus Module

Centralized Event System for Cross-Module Communication

The Event Bus Module provides a pub/sub event system for decoupled communication between modules, components, and services.


Features

  • Pub/Sub Pattern - Publish and subscribe to events
  • Namespaced Events - Organize events with namespaces (e.g., 'user:created')
  • Event Filtering - Filter events by data or conditions
  • Event History - Track event history for debugging
  • Integration with LiveComponents - Works seamlessly with LiveComponents
  • Integration with SSE - Integrate with Server-Sent Events
  • Wildcard Support - Subscribe to event patterns
  • Middleware Support - Transform or filter events with middleware

Quick Start

Basic Usage

import { EventBus } from './modules/event-bus/index.js';

// Create event bus
const bus = EventBus.create();

// Subscribe to an event
const unsubscribe = bus.on('user:created', (user) => {
    console.log('User created:', user);
});

// Emit an event
bus.emit('user:created', { id: 1, name: 'John' });

// Unsubscribe
unsubscribe();

Module System Integration

<!-- Enable global event bus -->
<script type="module">
    import { init } from './modules/event-bus/index.js';
    
    init({
        enableHistory: true,
        maxHistorySize: 100
    });
</script>

<!-- Access globally -->
<script>
    // Subscribe
    window.EventBus.on('user:created', (user) => {
        console.log('User created:', user);
    });
    
    // Emit
    window.EventBus.emit('user:created', { id: 1, name: 'John' });
</script>

API Reference

EventBus.create(config)

Create a new EventBus instance.

Parameters:

  • config.enableHistory - Enable event history (default: false)
  • config.maxHistorySize - Maximum history size (default: 100)
  • config.enableWildcards - Enable wildcard patterns (default: true)

Example:

const bus = EventBus.create({
    enableHistory: true,
    maxHistorySize: 50
});

bus.on(eventName, callback, options)

Subscribe to an event.

Parameters:

  • eventName - Event name (supports wildcards: 'user:', '')
  • callback - Callback function: (data, eventName, options) => void
  • options.once - Subscribe only once (default: false)
  • options.priority - Subscription priority (default: 0)
  • options.filter - Filter function: (data, options) => boolean

Returns: Unsubscribe function

Example:

// Basic subscription
const unsubscribe = bus.on('user:created', (user) => {
    console.log('User created:', user);
});

// Once subscription
bus.once('user:created', (user) => {
    console.log('User created (once):', user);
});

// Priority subscription
bus.on('user:created', (user) => {
    console.log('High priority handler');
}, { priority: 10 });

// Filtered subscription
bus.on('user:created', (user) => {
    console.log('Admin user created');
}, {
    filter: (user) => user.role === 'admin'
});

bus.once(eventName, callback, options)

Subscribe to an event once (auto-unsubscribe after first emission).

Parameters: Same as on()

Returns: Unsubscribe function

bus.off(eventName, callback)

Unsubscribe from an event.

Parameters:

  • eventName - Event name
  • callback - Callback function to remove

bus.emit(eventName, data, options)

Emit an event.

Parameters:

  • eventName - Event name
  • data - Event data
  • options - Event options

Example:

bus.emit('user:created', { id: 1, name: 'John' });
bus.emit('user:updated', { id: 1, name: 'Jane' }, { source: 'api' });

bus.use(middleware)

Add middleware to transform or filter events.

Parameters:

  • middleware - Middleware function: (eventName, data, options) => data | null | false

Example:

// Logging middleware
bus.use((eventName, data, options) => {
    console.log(`Event: ${eventName}`, data);
    return data; // Continue
});

// Filtering middleware
bus.use((eventName, data, options) => {
    if (eventName.startsWith('debug:')) {
        return null; // Block debug events in production
    }
    return data;
});

bus.getHistory(filter)

Get event history.

Parameters:

  • filter - Optional filter (string for event name, or function)

Returns: Array<EventHistoryItem>

Example:

// Get all history
const history = bus.getHistory();

// Get history for specific event
const userHistory = bus.getHistory('user:created');

// Get history with custom filter
const recentHistory = bus.getHistory((item) => {
    return Date.now() - item.timestamp < 60000; // Last minute
});

Namespaced Events

Organize events with namespaces:

// Subscribe to namespace
bus.on('user:*', (data, eventName) => {
    console.log(`User event: ${eventName}`, data);
});

// Emit namespaced events
bus.emit('user:created', { id: 1 });
bus.emit('user:updated', { id: 1 });
bus.emit('user:deleted', { id: 1 });

Wildcard Support

Subscribe to event patterns:

// Subscribe to all events
bus.on('*', (data, eventName) => {
    console.log(`Event: ${eventName}`, data);
});

// Subscribe to pattern
bus.on('user:*', (data, eventName) => {
    console.log(`User event: ${eventName}`, data);
});

Integration with LiveComponents

import { EventBus } from './modules/event-bus/index.js';
import { LiveComponentManager } from './modules/livecomponent/index.js';

const bus = EventBus.create();
const lcManager = LiveComponentManager.getInstance();

// Listen for LiveComponent events
bus.on('livecomponent:action-executed', (data) => {
    console.log('Action executed:', data);
});

// Emit LiveComponent events
lcManager.on('action-executed', (componentId, actionName, params) => {
    bus.emit('livecomponent:action-executed', {
        componentId,
        actionName,
        params
    });
});

Integration with SSE

import { EventBus } from './modules/event-bus/index.js';
import { SseClient } from './modules/sse/index.js';

const bus = EventBus.create();
const sse = new SseClient(['updates']);

// Forward SSE messages to event bus
sse.on('message', (data) => {
    bus.emit('sse:message', data);
});

// Listen for SSE events
bus.on('sse:message', (data) => {
    console.log('SSE message:', data);
});

Use Cases

Module Communication

// Module A
const bus = EventBus.create();
bus.emit('module-a:data-ready', { data: [...] });

// Module B
bus.on('module-a:data-ready', (data) => {
    processData(data);
});

Component Communication

// Component A
bus.emit('component:user-selected', { userId: 123 });

// Component B
bus.on('component:user-selected', (data) => {
    loadUserDetails(data.userId);
});

Global Notifications

// Emit notification
bus.emit('notification:show', {
    type: 'success',
    message: 'Operation completed'
});

// Listen for notifications
bus.on('notification:show', (data) => {
    showNotification(data.type, data.message);
});

Analytics Events

// Track events
bus.on('*', (data, eventName) => {
    // Send to analytics
    analytics.track(eventName, data);
});

Best Practices

  1. Use Namespaces - Organize events with namespaces (e.g., 'user:created')
  2. Document Events - Document all events and their data structures
  3. Use TypeScript - Use TypeScript definitions for type safety
  4. Clean Up Subscriptions - Always unsubscribe when done
  5. Use Middleware - Use middleware for cross-cutting concerns (logging, analytics)

Browser Support

  • Chrome/Edge: 90+
  • Firefox: 88+
  • Safari: 14+
  • Mobile: iOS 14+, Android Chrome 90+

Required Features:

  • ES2020 JavaScript
  • Map and Set support

Next: Continue with Phase 2 modules →