emit events of that type, and event contracts on any node run with each event they consume. Events need RequestScript 1.6.0. See Events in the RequestScript docs for the language rules.
- Only the owner emits. The organization that owns an event type is the only one that may emit it, from scripts running on its own nodes.
- Anyone consumes. Any organization may deploy an event contract for an event type, on any node, unless the type is
restricted. A restricted event type is consumed only by contracts its owner deployed. - Consumers pay for themselves. Whoever deployed an event contract pays for its runs, never the publisher.
Declaring an event type
An event type declares the fields its events carry, and has no body:OrderPlaced.req
POST /v1/events on a node of your organization, with the node’s API_KEY or a run token from one of your organization’s API clients for that node:
Response
- The node’s organization owns it. An event type belongs to the organization of the node it is declared on, because only that organization’s nodes may emit it. A run token from another organization is refused with
403. - Versions are immutable. Deploy a new version, such as
event com.example.OrderPlaced@2(...), to change it. Deploying a version that exists is refused with409. - Names are taken once. The first node to declare a path keeps it. Peers refuse the same name from another node.
- Peers learn about it right away. The node announces its event types to its peers after every deploy and delete.
Emitting events
A request or a contract emits an event withemit, giving every field:
Checkout.req
- Events are published only if the run succeeds, as a contract’s state is saved only if its call succeeds. A run that fails publishes nothing.
- Only your organization’s scripts emit. A script may emit your event type when it runs on one of your organization’s nodes and belongs to your organization: a run with the node’s
API_KEYor one of your API clients, or a contract your organization owns. Other organizations can still trigger your events by calling your contracts, such asCheckout, which emit as your organization. - A run may emit at most 16 events, each with at most 32 KiB of data as JSON. A run that exceeds either fails. Set
maxEventsPerRunandmaxEventDataBytesin the node’s configuration to change them.
emit, and POST /v1/run answers 422 with "error": "Script failed".
Consuming events
An event contract names the event type itconsumes. It declares no parameters, since the event’s fields are its parameters, and no return type:
OnOrderPlaced.req
POST /v1/contracts, like any contract, on any node that knows the event type.
- It consumes one version. An event contract consumes the version it names, or the latest version its node knows when you deploy it.
- It isn’t a resource. It runs only with events, so it doesn’t appear in
GET /v1/resources, and nobody can call it with made-up data. A contract keeps its kind across versions: an event contract can’t get a callable version, or the other way around. - It reads the event. Besides the fields, it reads the built-in variables
event(id,type,version,publishedAtanddepth) andcaller, the event’s owner and the node that published it. - It keeps state like any contract, saved only if its run succeeds.
- A restricted event type can only be consumed by its owner’s contracts. Any other organization’s deploy is refused with
403.
How events reach your contract
- Nodes announce what they have. Each node tells its peers which event types it declared and which event contracts it runs, signed with its key. A node joining the network asks each peer for its announcement.
- The publisher queues each event. When a run succeeds, its node signs each event with its key and attaches its membership token. It queues the event for its own event contracts, and once for each peer that runs event contracts consuming it.
- The publisher delivers it. Each peer gets the event at
POST /v1/events/deliver. The publisher retries with backoff, from 30 seconds up to an hour between attempts, until the peer accepts the event or the event is a day old. - The receiver checks it. The receiving node accepts the event only if its signature is the publisher’s, the operator’s membership token says the publisher belongs to the event type’s owner, it was published in the last day, and the node knows the event type.
- The receiver runs its event contracts. Each one runs once per event, even if the event is delivered twice. A run that fails is tried again, up to 3 times in all.
Membership tokens
When a node starts a session with the operator, and every five minutes after, it gets a membership token: the operator’s signed statement that the node belongs to its organization. It is a JWT signed with the same keys as run tokens, withaud stellarium:membership, sub the node’s public key, org its organization and use membership, and it lasts an hour. It can never be used as a run token, and a run token can never be used as one.
A node needs a membership token to emit events, and an OPERATOR_URL to check the tokens of events it receives.
Who pays
Emitting costs only the publishing run’s tokens. Each event contract’s run is paid by the organization that deployed it:- Free on your own nodes. An event contract deployed with the node’s
API_KEY, or by the node’s own organization, runs free. - Billed under a mandate elsewhere. When your API client deploys an event contract to another organization’s node, the node asks the operator for an event mandate with the client’s run token: your permission for the node to run that contract and bill you. Before each event, the node asks the operator to hold a run under the mandate. It is held and charged like your API client’s billed runs: at most the client’s maximum per run, within its monthly cap, at the node’s listed price.
Chains of events
An event contract may emit events of its own. Each event carries its chain: the event types before it, and the contracts that emitted or consumed them. To stop loops:- Chains are at most 4 events deep.
- A contract can’t emit an event type already in its chain.
- A contract can’t call a contract already in its chain, on its own node or another.
- An event contract can’t emit the event type it consumes. That deploy is refused with
400.
Event1, and event contract B consumes it. B can’t emit Event1. If B emits Event2, event contract C may consume it, but C can’t emit Event1 or Event2, or call A or B.
What to trust
- Events are signed and checked. A receiving node trusts the operator for which organization a node belongs to, and the publisher’s key for the event itself.
- A removed node can publish for a short while. A node removed from its organization can still publish with its last membership token until it expires, within an hour.
- Restricted delivery relies on announcements. A publishing node trusts a peer’s announcement of who deployed its event contracts when it decides whether to send it restricted events.
- Billing stops runaway chains. A node could start a fresh chain, but every event contract in a loop is paid for by the organization that deployed it.