Events & automation
record.created / updated, cron.tick, listeners and automation addon status.
In-process bus
sumeru/core/event is a synchronous publish/subscribe bus in the server process. Not an external broker.
package my_module import ( "context" "sumeru/core/event") func init() { event.Subscribe("record.created", onCreated)} func onCreated(ctx context.Context, ev event.Event) error { // Payload typically includes model / id after a committed mutation. _ = ev.Payload return nil}
Important event names
| Name | When |
|---|---|
record.created | After a committed create |
record.updated | After a committed write |
cron.tick | Scheduler fired a due sys.cron row |
Automation addon. Kernel automation subscribes to record.created, record.updated, and cron.tick to run matching sys.server.action rows. Declarative code prefixes publish: and write: are executed; unknown prefixes are logged at debug.
Server actions (declarative)
Define actions in data XML — no Go required for simple event chains or field writes:
<record id="action_followup" model="sys.server.action"> <field name="name">Follow-up event</field> <field name="event_name">record.updated</field> <field name="model">crm.lead</field> <field name="code">publish:crm.lead.followup</field> <field name="active" eval="True"/></record><record id="action_mark_done" model="sys.server.action"> <field name="name">Mark done</field> <field name="event_name">crm.lead.followup</field> <field name="code">write:{"active": false}</field> <field name="active" eval="True"/></record>
Cron Go handlers
Register a handler keyed by the sys.cron row's code field in addon init.go:
import "sumeru/core/scheduler" func init() { scheduler.RegisterCronHandler("my_module.nightly_digest", runNightlyDigest)}
The scheduler still publishes cron.tick and any custom event_name on the cron row. There is no Python/safe_eval — Go handlers only. CRM does not seed a sys.cron for lead assignment; use Assign Leads on the team form.
Outbox alignment
ORM mutations publish record.* for data that actually committed (outbox / mutation pipeline). A background drain worker (5s ticker) publishes pending sys.outbox.event rows asynchronously after commit. Do not emit business events for rolled-back work.
Compile and run
Listeners register in init via blank-imports. Restart the server after changing handler code:
make generatemake run
What not to do
- Do not block the bus with long network calls. Keep handlers short or queue work yourself.
- Do not assume multi-process fan-out; each process has its own bus.
- Do not rely on event ordering guarantees beyond what the current engine documents.
Next step
Call models over HTTP in JSON-RPC API, or read Event bus.