feat(broker): migrations-based install, roles, RLS, and job dependency groups

Replace the ad-hoc tables/procedures install layout with versioned,
ordered SQL migrations tracked in broker_schema_migrations. Add
optional least-privilege role provisioning (--with-roles), multi-tenant
row-level security, lease-based job claiming with stale-lease recovery,
and job dependencies -- both by job id and by fan-in job group. Add
Docker/Compose support for running the broker and its test suite.
This commit is contained in:
2026-09-17 22:09:41 +02:00
parent 602997bcdb
commit 4c8e1066d4
53 changed files with 2911 additions and 1016 deletions
+9 -14
View File
@@ -6,7 +6,6 @@ import (
"sync"
"git.warky.dev/wdevs/pgsql-broker/pkg/broker/adapter"
"git.warky.dev/wdevs/pgsql-broker/pkg/broker/models"
"git.warky.dev/wdevs/pgsql-broker/pkg/broker/worker"
)
@@ -33,6 +32,8 @@ type Config struct {
BufferSize int
TimerSeconds int
FetchSize int
TenantID string
LeaseSeconds int
}
// New creates a new queue manager
@@ -70,6 +71,8 @@ func (q *Queue) Start(cfg Config) error {
BufferSize: cfg.BufferSize,
TimerSeconds: cfg.TimerSeconds,
FetchSize: cfg.FetchSize,
TenantID: cfg.TenantID,
LeaseSeconds: cfg.LeaseSeconds,
})
if err := w.Start(q.ctx); err != nil {
@@ -109,24 +112,16 @@ func (q *Queue) Stop() error {
return nil
}
// AddJob adds a job to the least busy worker
func (q *Queue) AddJob(job models.Job) error {
// Wake signals every worker in the queue to check for available jobs
// immediately. There is no job hand-off: fetching is always DB-driven via
// broker_get, so waking a worker that finds nothing is harmless.
func (q *Queue) Wake() {
q.mu.RLock()
defer q.mu.RUnlock()
if len(q.workers) == 0 {
return fmt.Errorf("no workers available")
}
// Simple round-robin: use first available worker
// Could be enhanced with load balancing
for _, w := range q.workers {
if err := w.AddJob(job); err == nil {
return nil
}
w.Wake()
}
return fmt.Errorf("all workers are busy")
}
// GetStats returns statistics for all workers in the queue