Record customer events in SQLite
Subscribe to a named event and keep a durable application record without turning the workflow into a web of callback code.
This workflow listens for customer.updated, validates every publication, and writes the accepted event to a separate application database. The event can come from services.events.emit() in another loaded workflow or from WOML’s authenticated event ingress.
The workflow
WOML
<woml>
<workflow
id="customer-event-ledger"
name="Customer event ledger"
description="Record validated customer updates in SQLite."
version="1.0.0"
>
<config concurrency="4" queue="customer-events" />
<triggers>
<event id="customerUpdated" name="customer.updated">
<schema>
{
"type": "object",
"required": ["customerId", "change"],
"properties": {
"customerId": { "type": "string" },
"change": { "type": "string" }
},
"additionalProperties": false
}
</schema>
</event>
</triggers>
<steps>
<step id="recordEvent" name="Record customer update">
<script>
const db = services.db({
driver: "sqlite",
connection: "./data/customer-events.sqlite"
});
await db.execute({
text: `
CREATE TABLE IF NOT EXISTS customer_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id TEXT NOT NULL,
change TEXT NOT NULL,
recorded_at TEXT NOT NULL
)
`
}, { name: "ensure-customer-events-table" });
const recordedAt = new Date().toISOString();
const result = await db.insert({
table: "customer_events",
values: {
customer_id: context.payload.customerId,
change: context.payload.change,
recorded_at: recordedAt
}
}, { name: "record-customer-event" });
return {
customerId: context.payload.customerId,
recordedAt,
rowId: result.lastInsertId
};
</script>
</step>
</steps>
</workflow>
</woml>Run it
Create the data directory before activation, then validate and run the workflow alongside any publishers that emit customer.updated.
Terminal
mkdir -p data
woml check customer-event-ledger.woml
woml run customer-event-ledger.womlThe SQLite file is application data and must remain separate from WOML’s runtime-state database. Parameterized database helpers and stable operation names keep the write explicit and supervised.