001-platform-events.xml
2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">
<!--
platform__event_outbox
The transactional outbox table for the vibe_erp event bus.
Why an outbox at all (architecture spec section 9, "Cross-cutting"):
the bus must guarantee "publish-and-rollback can never escape" —
i.e. an event published inside a transaction is delivered if and
only if the surrounding transaction commits. The way to do that
without two-phase commit between the DB and the message broker is
to write the event row to the SAME database in the SAME transaction
as the originating change. A separate poller picks up DISPATCHED
rows and forwards them to in-process subscribers (today) or to
Kafka/NATS (later) — and a publish that gets rolled back simply
leaves no row to dispatch.
Status machine:
PENDING — written by publish(), not yet picked up
DISPATCHED — successfully delivered to all subscribers
FAILED — delivery failed; will retry until attempts >= max
-->
<changeSet id="platform-events-001" author="vibe_erp">
<comment>Create platform__event_outbox table</comment>
<sql>
CREATE TABLE platform__event_outbox (
id uuid PRIMARY KEY,
event_id uuid NOT NULL,
topic varchar(256) NOT NULL,
aggregate_type varchar(128) NOT NULL,
aggregate_id varchar(256) NOT NULL,
payload jsonb NOT NULL,
status varchar(16) NOT NULL DEFAULT 'PENDING',
attempts integer NOT NULL DEFAULT 0,
last_error text,
occurred_at timestamptz NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
dispatched_at timestamptz,
version bigint NOT NULL DEFAULT 0
);
CREATE UNIQUE INDEX platform__event_outbox_event_id_uk
ON platform__event_outbox (event_id);
CREATE INDEX platform__event_outbox_status_created_idx
ON platform__event_outbox (status, created_at);
CREATE INDEX platform__event_outbox_topic_idx
ON platform__event_outbox (topic);
</sql>
<rollback>
DROP TABLE platform__event_outbox;
</rollback>
</changeSet>
</databaseChangeLog>