mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-12-13 17:10:36 +00:00
328 lines
8.9 KiB
Markdown
328 lines
8.9 KiB
Markdown
# Event Broker System
|
|
|
|
A comprehensive event handler/broker system for ResolveSpec that provides real-time event publishing, subscription, and cross-instance communication.
|
|
|
|
## Features
|
|
|
|
- **Multiple Sources**: Events from database, websockets, frontend, system, and internal sources
|
|
- **Event Status Tracking**: Pending, processing, completed, failed states with timestamps
|
|
- **Rich Metadata**: User IDs, session IDs, instance IDs, JSON payloads, and custom metadata
|
|
- **Sync & Async Modes**: Choose between synchronous or asynchronous event processing
|
|
- **Pattern Matching**: Subscribe to events using glob-style patterns
|
|
- **Multiple Providers**: In-memory, Redis Streams, NATS JetStream, PostgreSQL with NOTIFY
|
|
- **Hook Integration**: Automatic CRUD event capture via restheadspec hooks
|
|
- **Retry Logic**: Configurable retry policy with exponential backoff
|
|
- **Metrics**: Prometheus-compatible metrics for monitoring
|
|
- **Graceful Shutdown**: Proper cleanup and event flushing on shutdown
|
|
|
|
## Quick Start
|
|
|
|
### 1. Configuration
|
|
|
|
Add to your `config.yaml`:
|
|
|
|
```yaml
|
|
event_broker:
|
|
enabled: true
|
|
provider: memory # memory, redis, nats, database
|
|
mode: async # sync, async
|
|
worker_count: 10
|
|
buffer_size: 1000
|
|
instance_id: "${HOSTNAME}"
|
|
```
|
|
|
|
### 2. Initialize
|
|
|
|
```go
|
|
import (
|
|
"github.com/bitechdev/ResolveSpec/pkg/config"
|
|
"github.com/bitechdev/ResolveSpec/pkg/eventbroker"
|
|
)
|
|
|
|
func main() {
|
|
// Load configuration
|
|
cfgMgr := config.NewManager()
|
|
cfg, _ := cfgMgr.GetConfig()
|
|
|
|
// Initialize event broker
|
|
if err := eventbroker.Initialize(cfg.EventBroker); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Subscribe to Events
|
|
|
|
```go
|
|
// Subscribe to specific events
|
|
eventbroker.Subscribe("public.users.create", eventbroker.EventHandlerFunc(
|
|
func(ctx context.Context, event *eventbroker.Event) error {
|
|
log.Printf("New user created: %s", event.Payload)
|
|
// Send welcome email, update cache, etc.
|
|
return nil
|
|
},
|
|
))
|
|
|
|
// Subscribe with patterns
|
|
eventbroker.Subscribe("*.*.delete", eventbroker.EventHandlerFunc(
|
|
func(ctx context.Context, event *eventbroker.Event) error {
|
|
log.Printf("Deleted: %s.%s", event.Schema, event.Entity)
|
|
return nil
|
|
},
|
|
))
|
|
```
|
|
|
|
### 4. Publish Events
|
|
|
|
```go
|
|
// Create and publish an event
|
|
event := eventbroker.NewEvent(eventbroker.EventSourceDatabase, "public.users.update")
|
|
event.InstanceID = eventbroker.GetDefaultBroker().InstanceID()
|
|
event.UserID = 123
|
|
event.SessionID = "session-456"
|
|
event.Schema = "public"
|
|
event.Entity = "users"
|
|
event.Operation = "update"
|
|
|
|
event.SetPayload(map[string]interface{}{
|
|
"id": 123,
|
|
"name": "John Doe",
|
|
})
|
|
|
|
// Async (non-blocking)
|
|
eventbroker.PublishAsync(ctx, event)
|
|
|
|
// Sync (blocking)
|
|
eventbroker.PublishSync(ctx, event)
|
|
```
|
|
|
|
## Automatic CRUD Event Capture
|
|
|
|
Automatically capture database CRUD operations:
|
|
|
|
```go
|
|
import (
|
|
"github.com/bitechdev/ResolveSpec/pkg/eventbroker"
|
|
"github.com/bitechdev/ResolveSpec/pkg/restheadspec"
|
|
)
|
|
|
|
func setupHooks(handler *restheadspec.Handler) {
|
|
broker := eventbroker.GetDefaultBroker()
|
|
|
|
// Configure which operations to capture
|
|
config := eventbroker.DefaultCRUDHookConfig()
|
|
config.EnableRead = false // Disable read events for performance
|
|
|
|
// Register hooks
|
|
eventbroker.RegisterCRUDHooks(broker, handler.Hooks(), config)
|
|
|
|
// Now all create/update/delete operations automatically publish events!
|
|
}
|
|
```
|
|
|
|
## Event Structure
|
|
|
|
Every event contains:
|
|
|
|
```go
|
|
type Event struct {
|
|
ID string // UUID
|
|
Source EventSource // database, websocket, system, frontend, internal
|
|
Type string // Pattern: schema.entity.operation
|
|
Status EventStatus // pending, processing, completed, failed
|
|
Payload json.RawMessage // JSON payload
|
|
UserID int // User who triggered the event
|
|
SessionID string // Session identifier
|
|
InstanceID string // Server instance identifier
|
|
Schema string // Database schema
|
|
Entity string // Database entity/table
|
|
Operation string // create, update, delete, read
|
|
CreatedAt time.Time // When event was created
|
|
ProcessedAt *time.Time // When processing started
|
|
CompletedAt *time.Time // When processing completed
|
|
Error string // Error message if failed
|
|
Metadata map[string]interface{} // Additional context
|
|
RetryCount int // Number of retry attempts
|
|
}
|
|
```
|
|
|
|
## Pattern Matching
|
|
|
|
Subscribe to events using glob-style patterns:
|
|
|
|
| Pattern | Matches | Example |
|
|
|---------|---------|---------|
|
|
| `*` | All events | Any event |
|
|
| `public.users.*` | All user operations | `public.users.create`, `public.users.update` |
|
|
| `*.*.create` | All create operations | `public.users.create`, `auth.sessions.create` |
|
|
| `public.*.*` | All events in public schema | `public.users.create`, `public.posts.delete` |
|
|
| `public.users.create` | Exact match | Only `public.users.create` |
|
|
|
|
## Providers
|
|
|
|
### Memory Provider (Default)
|
|
|
|
Best for: Development, single-instance deployments
|
|
|
|
- **Pros**: Fast, no dependencies, simple
|
|
- **Cons**: Events lost on restart, single-instance only
|
|
|
|
```yaml
|
|
event_broker:
|
|
provider: memory
|
|
```
|
|
|
|
### Redis Provider (Future)
|
|
|
|
Best for: Production, multi-instance deployments
|
|
|
|
- **Pros**: Persistent, cross-instance pub/sub, reliable
|
|
- **Cons**: Requires Redis
|
|
|
|
```yaml
|
|
event_broker:
|
|
provider: redis
|
|
redis:
|
|
stream_name: "resolvespec:events"
|
|
consumer_group: "resolvespec-workers"
|
|
host: "localhost"
|
|
port: 6379
|
|
```
|
|
|
|
### NATS Provider (Future)
|
|
|
|
Best for: High-performance, low-latency requirements
|
|
|
|
- **Pros**: Very fast, built-in clustering, durable
|
|
- **Cons**: Requires NATS server
|
|
|
|
```yaml
|
|
event_broker:
|
|
provider: nats
|
|
nats:
|
|
url: "nats://localhost:4222"
|
|
stream_name: "RESOLVESPEC_EVENTS"
|
|
```
|
|
|
|
### Database Provider (Future)
|
|
|
|
Best for: Audit trails, event replay, SQL queries
|
|
|
|
- **Pros**: No additional infrastructure, full SQL query support, PostgreSQL NOTIFY for real-time
|
|
- **Cons**: Slower than Redis/NATS
|
|
|
|
```yaml
|
|
event_broker:
|
|
provider: database
|
|
database:
|
|
table_name: "events"
|
|
channel: "resolvespec_events"
|
|
```
|
|
|
|
## Processing Modes
|
|
|
|
### Async Mode (Recommended)
|
|
|
|
Events are queued and processed by worker pool:
|
|
|
|
- Non-blocking event publishing
|
|
- Configurable worker count
|
|
- Better throughput
|
|
- Events may be processed out of order
|
|
|
|
```yaml
|
|
event_broker:
|
|
mode: async
|
|
worker_count: 10
|
|
buffer_size: 1000
|
|
```
|
|
|
|
### Sync Mode
|
|
|
|
Events are processed immediately:
|
|
|
|
- Blocking event publishing
|
|
- Guaranteed ordering
|
|
- Immediate error feedback
|
|
- Lower throughput
|
|
|
|
```yaml
|
|
event_broker:
|
|
mode: sync
|
|
```
|
|
|
|
## Retry Policy
|
|
|
|
Configure automatic retries for failed handlers:
|
|
|
|
```yaml
|
|
event_broker:
|
|
retry_policy:
|
|
max_retries: 3
|
|
initial_delay: 1s
|
|
max_delay: 30s
|
|
backoff_factor: 2.0 # Exponential backoff
|
|
```
|
|
|
|
## Metrics
|
|
|
|
The event broker exposes Prometheus metrics:
|
|
|
|
- `eventbroker_events_published_total{source, type}` - Total events published
|
|
- `eventbroker_events_processed_total{source, type, status}` - Total events processed
|
|
- `eventbroker_event_processing_duration_seconds{source, type}` - Event processing duration
|
|
- `eventbroker_queue_size` - Current queue size (async mode)
|
|
|
|
## Best Practices
|
|
|
|
1. **Use Async Mode**: For better performance, use async mode in production
|
|
2. **Disable Read Events**: Read events can be high volume; disable if not needed
|
|
3. **Pattern Matching**: Use specific patterns to avoid processing unnecessary events
|
|
4. **Error Handling**: Always handle errors in event handlers; they won't fail the original operation
|
|
5. **Idempotency**: Make handlers idempotent as events may be retried
|
|
6. **Payload Size**: Keep payloads reasonable; avoid large objects
|
|
7. **Monitoring**: Monitor metrics to detect issues early
|
|
|
|
## Examples
|
|
|
|
See `example_usage.go` for comprehensive examples including:
|
|
- Basic event publishing and subscription
|
|
- Hook integration
|
|
- Error handling
|
|
- Configuration
|
|
- Pattern matching
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────┐
|
|
│ Application │
|
|
└────────┬────────┘
|
|
│
|
|
├─ Publish Events
|
|
│
|
|
┌────────▼────────┐ ┌──────────────┐
|
|
│ Event Broker │◄────►│ Subscribers │
|
|
└────────┬────────┘ └──────────────┘
|
|
│
|
|
├─ Store Events
|
|
│
|
|
┌────────▼────────┐
|
|
│ Provider │
|
|
│ (Memory/Redis │
|
|
│ /NATS/DB) │
|
|
└─────────────────┘
|
|
```
|
|
|
|
## Future Enhancements
|
|
|
|
- [ ] Database Provider with PostgreSQL NOTIFY
|
|
- [ ] Redis Streams Provider
|
|
- [ ] NATS JetStream Provider
|
|
- [ ] Event replay functionality
|
|
- [ ] Dead letter queue
|
|
- [ ] Event filtering at provider level
|
|
- [ ] Batch publishing
|
|
- [ ] Event compression
|
|
- [ ] Schema versioning
|