uip | title | description | author | status | type | category | created |
---|---|---|---|---|---|---|---|
0116 |
Arvo Ticks |
Pin Arvo's scry handler to a move tick |
~wicdev-wisryt, ~rovnys-ricfer |
Draft |
Standards Track |
Kernel |
2023-08-30 |
Introduce the concept of an Arvo "tick" -- a number that Arvo tracks that increments every time Arvo runs a vane. This tick can be used in scry paths to request data at the latest available tick.
This replaces the commonly used pattern of scrying at the current date, which is convenient but violates referential transparency: an agent could scry into another agent at the current date; then poke that agent, changing its state; then scry at the (unchanged) current date again, and receive a different answer. Scrying at the latest tick preserves the convenience of being able to read synchronously from the state of another module (vane or agent), but it ensures referential transparency.
When built in a breadth-first Arvo kernel, this tick system enables a kind of simultaneity that enables notifications, including breach notices, to be delivered to multiple vanes "simultaneously", i.e. it will be unobservable to any code in the system whether any of those vanes were run before other vanes -- this commutativity should also enable a sufficiently smart interpreter to execute these vane activations in parallel.
Arvo will track a "tick" value in its persistent state. Every time it activates a vane, it increments that tick. The tick could start at 0 on initial boot.
The $case
datatype will have a new option added to it to represent a tick: [%ux p=@ux]
. Alternatively, this could look like [%tick p=@ud]
, but making the tag anything other than an aura would break any client code that does things like =/ =case ud+3 (scot case)
.
Arvo will set the scry handler for a vane activation to the gate it created just after the vane activation that emitted the move that the new vane is about to handle. When the vane runs, Arvo will give it this "pinned" scry handler and the tick at which it was pinned. This allows the vane (and any userspace code the vane runs) to scry at the supplied tick.
The implementation in Arvo will add two fields to the $germ
datatype: a tick and a scry handler gate. When Arvo activates a vane, it will read from the $germ
in the $plan
move-list and supply those tick and scry-handler values into the vane as part of its $vane-sample
contextual information. When the vane finishes running, Arvo will increment its tick and store the new tick and a freshly generated scry gate in the new $germ
that forms the head of the new $plan
, so that when whose moves are executed later, their tick and scry handler will be pinned appropriately.
TODO: What should Arvo do if a single activation of, say, Gall, emits two moves to Ames? Will both moves have their scry gate pinned, even though the first move was handled first? That would mean the second activation of Ames wouldn't be able to scry into the latest version of itself that had just run. This could be an issue if Ames scrys into some other vane, which scrys back into Ames -- that other vane would see an old version of Ames that hadn't processed the first move yet. I think this is better than the alternative, though, which is that Arvo would increment the tick delivered to Ames the second time; that would work well for this example, but would be confusing when delivering subscription updates to multiple Gall agents, which is a less contrived example.
Vanes will need to change their +scry
arms to support ephemeral scrying only at the latest tick, instead of only at the current date. Gall agent +on-peek
arms should similarly be modified. The $bowl:agent:gall
will need to be augmented with the latest tick to allow the agent to scry at that tick. We should delete Jael's hack that inspects ducts to determine the order in which it should deliver public key change notifications.
TODO: Should Gall agents be allowed to scry into each other during +on-load
? We could potentially split +on-load
into two activations. The first would take in an old state and return a new state, but no effects, and scry would be prohibited. The second would allow scrying and allow effects to be emitted. In a breadth-first Arvo with ticks, this arrangement should be sound. The downside is that agents would end up with extra temporary state between the two phases of an upgrade.
TODO: How should Clay handle queries at the current date?
Userspace code should be rewritten to scry into vanes and other agents at the latest tick rather than the current date. Scrying at the current date should fail for any ephemeral query (i.e. anything other than deliberately preserved historical data, such as old Clay commits), since it's not referentially transparent.
All major applications should be tested to make sure their scrys all use the latest tick instead of the current date.
Ticks should not be exposed over the network. Remote scry protocols should not support scrying at a tick case.
TODO
Copyright and related rights waived via CC0.