Deadlines and expiry
How a worker knows when to fire, when Arkiv sends no event for expiry.
Arkiv emits events when an entity is created, updated, extended, has its owner changed, or is deleted.
It emits nothing when an entity expires: the entity just stops appearing in queries. An expired
entity and a deleted one look the same to getEntity (both throw "not found").
So a worker computes each rule's deadline itself and checks it on its own clock:
| Trigger | Deadline |
|---|---|
on: 'block' | fireat - offset |
on: 'expire' | the target's current $expiresAt - offset |
The worker checks deadlines every 4 seconds (two blocks).
The target can change
- Extended: the extension arrives as an event, and the deadline moves with it. The rule fires later.
- Deleted: the deletion arrives as an event (and is replayed after a worker restart from Arkiv's
logs). At the deadline the worker records a
skippedreceipt, "the target was deleted before it expired", instead of firing. - Gone when first seen: the deadline is now.
Before firing, a worker always reads the target once more, so an extension that raced the deadline is honoured.
Blocks and time
Tiramisu makes a block about every 2 seconds. Dates are converted with the chain's current block and
time (toBlock, toDate), so a date-and-time rule fires within a block or two of the minute you picked.
Latency
A worker notices a new rule within about 30 seconds (it re-reads rules at most every 30 seconds; see Access keys and quota) and claims it 8 blocks before the deadline. In tests, rules fired a median of 0 to 1 blocks after their deadline. A rule created less than about 30 seconds before its deadline can fire late by up to that much.