# 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

Best for: Production, multi-instance deployments

- **Pros**: Persistent, cross-instance pub/sub, reliable, Redis Streams support
- **Cons**: Requires Redis server
- **Status**: ✅ Implemented

```yaml
event_broker:
  provider: redis
  redis:
    stream_name: "resolvespec:events"
    consumer_group: "resolvespec-workers"
    max_len: 10000
    host: "localhost"
    port: 6379
    password: ""
    db: 0
```

### NATS Provider

Best for: High-performance, low-latency requirements

- **Pros**: Very fast, built-in clustering, durable, JetStream support
- **Cons**: Requires NATS server
- **Status**: ✅ Implemented

```yaml
event_broker:
  provider: nats
  nats:
    url: "nats://localhost:4222"
    stream_name: "RESOLVESPEC_EVENTS"
    storage: "file"  # or "memory"
    max_age: "24h"
```

### Database Provider

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, requires database connection
- **Status**: ✅ Implemented

```yaml
event_broker:
  provider: database
  database:
    table_name: "events"
    channel: "resolvespec_events"
    poll_interval: "1s"
```

## 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)     │
└─────────────────┘
```

## Implemented Features

- [x] Memory Provider (in-process, single-instance)
- [x] Redis Streams Provider (distributed, persistent)
- [x] NATS JetStream Provider (distributed, high-performance)
- [x] Database Provider with PostgreSQL NOTIFY (SQL-queryable, audit-friendly)
- [x] Sync and Async processing modes
- [x] Pattern-based subscriptions
- [x] Hook integration for automatic CRUD events
- [x] Retry policy with exponential backoff
- [x] Graceful shutdown

## Future Enhancements

- [ ] Event replay functionality from specific timestamp
- [ ] Dead letter queue for failed events
- [ ] Event filtering at provider level for performance
- [ ] Batch publishing support
- [ ] Event compression for large payloads
- [ ] Schema versioning and migration
- [ ] Event streaming to external systems (Kafka, RabbitMQ)
- [ ] Event aggregation and analytics
