Zornux docs
Get started Spec

Data & Enterprise

Messaging & the Event Bus

Zornux has a built-in event bus. You declare an event, subscribe to it with a handler, and publish — and the language fans the message out to every subscriber. It's the last major application programming model: event-driven, publish/subscribe, and decoupled.

Events, handlers, publish

An event … end is a named message contract. A handler Name for Event with e … end subscribes to it, reading the payload through e. publish Event with … raises it.

zornux
event UserRegistered
    has user_id
    has email
end

handler SendWelcome for UserRegistered with e
    show "Welcome " + e.email
end

publish UserRegistered with user_id 42, email "[email protected]"
Decoupled by design

Publishing doesn't run the handlers — it enqueues one delivery per subscriber onto the background queue. Handlers run when work drains (end of the script, the end of a web request, or a serving worker), so publish never blocks. Every subscriber is notified, in declaration order.

Handlers are components

A handler is a first-class component, just like a service: it injects dependencies with use and carries its own delivery retry policy.

zornux
handler SendWelcome for UserRegistered with e retry 3 times waiting 30 seconds
    use Mailer          # inject a service, repository, or configuration
    use AppConfig
    Mailer.send(e.email, AppConfig.greeting)
end
ClauseRole
for EventThe event this handler subscribes to.
with eBinds the published payload (optional).
use NameInjects a dependency — a missing one is ZX2503, exactly like a service.
retry N times [waiting M seconds]Re-deliver on failure; the final failure is a dead-letter.

Publish from anywhere

A publish works at the top level, inside a route, a job, or a service method — so a request can announce a domain event and unrelated handlers react.

zornux
controller Signups at "/signup"
    on POST "/"
        save user into Db.Users
        publish UserRegistered with user_id user.id, email user.email
        give back created
    end
end
publish, one keyword, two shapes

publish X on port N starts a web block; publish X with … (or a bare publish X) raises an event. The on tells them apart. No new reserved keywordsevent and handler are contextual, so create event = 1 and create handler = 2 still bind ordinary variables.

Reliable delivery

Because deliveries ride the background queue, they inherit its whole story: a failing handler is contained, retried on the deterministic timeline, and dead-lettered on final failure — with automatic messaging log events (a warning per retry, an error on the dead-letter, each carrying the handler and event names).

Introspection & health

Three built-ins read the bus, and GET /health gains an events block:

zornux
show events_published()    # events raised this run
show handlers_pending()    # deliveries awaiting the drain
show events_failed()       # dead-lettered deliveries
json
{
  "status": "healthy",
  "events": { "published": 12, "pending": 0, "failed": 1 }
}

Diagnostics

CodeMeaning
ZX3200There's no event with that name.
ZX3201The event has no such field.
ZX3202Malformed publish (e.g. a field set twice).
In-process today

The v1 bus is in-process and in-memory — perfect for a single service and its background work. A distributed transport and durable event store are a documented future seam; this is the local half of that model.

Diagnostics are ZX3200ZX3299. Built on background processing.