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
- 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
7.7 KiB
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) => voidoptions.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 namecallback- Callback function to remove
bus.emit(eventName, data, options)
Emit an event.
Parameters:
eventName- Event namedata- Event dataoptions- 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
- Use Namespaces - Organize events with namespaces (e.g., 'user:created')
- Document Events - Document all events and their data structures
- Use TypeScript - Use TypeScript definitions for type safety
- Clean Up Subscriptions - Always unsubscribe when done
- 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 →