replace tokio::broadcast event bus with SQLite-backed event queue (ADR-0003)

- DomainEvent: add Serialize/Deserialize
- EventConsumer port: poll_next/ack/nack replacing recv()
- EventEnvelope: wraps event with id/retry_count/created_at
- SqliteEventPublisher/SqliteEventConsumer: INSERT/poll/DLQ
- migration: event_queue + dead_letter_queue tables
- InMemoryEventBus: combined publisher+consumer test double
- NoopEventConsumer: test stub
- webhook_consumer: polls EventConsumer instead of broadcast::Receiver
- presentation+mcp wiring: create from SqlitePool
This commit is contained in:
2026-07-12 07:23:21 +02:00
parent e2393be635
commit 826e824b58
13 changed files with 380 additions and 55 deletions

View File

@@ -0,0 +1,25 @@
CREATE TABLE IF NOT EXISTS event_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_type TEXT NOT NULL,
payload TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
retry_count INTEGER NOT NULL DEFAULT 0,
max_retries INTEGER NOT NULL DEFAULT 3,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
error_message TEXT
);
CREATE TABLE IF NOT EXISTS dead_letter_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
original_event_id INTEGER NOT NULL,
event_type TEXT NOT NULL,
payload TEXT NOT NULL,
error_message TEXT NOT NULL,
retry_count INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
original_created_at TEXT NOT NULL
);
CREATE INDEX idx_event_queue_status ON event_queue(status);
CREATE INDEX idx_event_queue_created_at ON event_queue(created_at);