Events & jobs
Modules collaborate without knowing each other through two PostgreSQL mechanisms: an event bus (LISTEN/NOTIFY) and a job queue (SKIP LOCKED).
Events #
A module declares in its manifest what it publishes and what it is subscribed to. The core relays via LISTEN/NOTIFY and logs into core.event_log. Real examples (calendar):
publishes = ["EventCreated", "EventUpdated", "EventDeleted"]
subscribed = ["UserDeleted", "ContactUpdated"]Typical payload (JSON):
{ "type": "EventCreated",
"payload": { "event_id": "…", "user_id": "…", "module_id": "calendar" } }React to UserDeleted, for example, to purge the user's data from your schema — this is how consistency is kept without direct coupling between modules.
Job queue (SKIP LOCKED) #
For asynchronous work (emails, exports, cleanup, webhooks), push a job into core.jobs; workers claim it with safe concurrency:
SELECT id FROM core.jobs
WHERE status = 'pending' AND run_after <= NOW()
FOR UPDATE SKIP LOCKED
LIMIT 10;Key fields: job_type, payload (JSONB), status (pending → running → done/failed), attempts/max_attempts, run_after (scheduling & retry).