feat: implement per-webhook event databases
All checks were successful
check / check (push) Successful in 1m50s
All checks were successful
check / check (push) Successful in 1m50s
Split data storage into main application DB (config only) and
per-webhook event databases (one SQLite file per webhook).
Architecture changes:
- New WebhookDBManager component manages per-webhook DB lifecycle
(create, open, cache, delete) with lazy connection pooling via sync.Map
- Main DB (DBURL) stores only config: Users, Webhooks, Entrypoints,
Targets, APIKeys
- Per-webhook DBs (DATA_DIR) store Events, Deliveries, DeliveryResults
in files named events-{webhook_uuid}.db
- New DATA_DIR env var (default: ./data dev, /data/events prod)
Behavioral changes:
- Webhook creation creates per-webhook DB file
- Webhook deletion hard-deletes per-webhook DB file (config soft-deleted)
- Event ingestion writes to per-webhook DB, not main DB
- Delivery engine polls all per-webhook DBs for pending deliveries
- Database target type marks delivery as immediately successful (events
are already in the dedicated per-webhook DB)
- Event log UI reads from per-webhook DBs with targets from main DB
- Existing webhooks without DB files get them created lazily
Removed:
- ArchivedEvent model (was a half-measure, replaced by per-webhook DBs)
- Event/Delivery/DeliveryResult removed from main DB migrations
Added:
- Comprehensive tests for WebhookDBManager (create, delete, lazy
creation, delivery workflow, multiple webhooks, close all)
- Dockerfile creates /data/events directory
README updates:
- Per-webhook event databases documented as implemented (was Phase 2)
- DATA_DIR added to configuration table
- Docker instructions updated with data volume mount
- Data model diagram updated
- TODO updated (database separation moved to completed)
Closes #15
This commit is contained in:
@@ -30,6 +30,7 @@ func TestHandleIndex(t *testing.T) {
|
||||
return &config.Config{
|
||||
// This is a base64 encoded 32-byte key: "test-session-key-32-bytes-long!!"
|
||||
SessionKey: "dGVzdC1zZXNzaW9uLWtleS0zMi1ieXRlcy1sb25nISE=",
|
||||
DataDir: t.TempDir(),
|
||||
}
|
||||
},
|
||||
func() *database.Database {
|
||||
@@ -37,6 +38,7 @@ func TestHandleIndex(t *testing.T) {
|
||||
db := &database.Database{}
|
||||
return db
|
||||
},
|
||||
database.NewWebhookDBManager,
|
||||
healthcheck.New,
|
||||
session.New,
|
||||
New,
|
||||
@@ -64,12 +66,14 @@ func TestRenderTemplate(t *testing.T) {
|
||||
return &config.Config{
|
||||
// This is a base64 encoded 32-byte key: "test-session-key-32-bytes-long!!"
|
||||
SessionKey: "dGVzdC1zZXNzaW9uLWtleS0zMi1ieXRlcy1sb25nISE=",
|
||||
DataDir: t.TempDir(),
|
||||
}
|
||||
},
|
||||
func() *database.Database {
|
||||
// Mock database
|
||||
return &database.Database{}
|
||||
},
|
||||
database.NewWebhookDBManager,
|
||||
healthcheck.New,
|
||||
session.New,
|
||||
New,
|
||||
|
||||
Reference in New Issue
Block a user