You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Cyclic promise resolutions interfere with our desired "retire upon resolution" pattern (#1124). To overcome this, @FUDCo has been working on batched resolutions: a single dispatch.notify() crank resolves multiple promises at the same time, so they can all be deserialized before any of the identifiers are retired. This has an ordering side-effect: the secondary promises get resolved earlier than they would have otherwise (our current scheduler is straight FIFO).
It occurred to me to think about how this will interact with the escalator schedulers. Resolution notifications can cause just as much work as a message delivery, so we want the notifications to travel on escalators just like deliveries. However if we're resolving multiple promises in a single notification, which escalator should it use? The simplest answer is to use the first promise in the batch (the one which was resolved first, and which dragged in all the others).
With an escalator-based scheduler, this changes the ordering side-effect somewhat: the secondary promises might get resolved earlier or later than they would have otherwise. Whoever is paying for the primary notification will also wind up paying for the secondaries. The secondary might get higher priority than they paid for, or they might pay for higher priority but not get it because the primary isn't paying for it.
Potential Solutions
Other than accepting the scheduling side-effect, I can think of a few possible answers:
Track all the escalators used by the full set of promises in the bundle, and deliver the batch as soon as the first one becomes ready. This would let promises resolve earlier than expected but never later than expected. This sounds complex, and doesn't solve the full problem.
Switch back to single-promise resolutions (remove batches), abandon "retire upon resolution", and use an explicit retire() message (something like dropImport, which would probably overlap with the GC/deallocation work). Each notification would travel its own escalator as usual, and be delivered exactly when its payment says so. The kernel would need to keep track of all the resolution notifications whose data references each other, and defer retiring the identifiers until all the notifications made it past the escalators and get delivered. This sounds even more complex, but probably solves the full problem.
Since delivering a bundle of promises in a batch is really about managing the vat-kernel relationship rather than about resolving the promises per se, another approach that occurs to me would be to split the action taken when a promise resolution is delivered into a vat into two steps: (1) note the resolution value somewhere inside liveslots, then (2) actually resolve the underlying JS promise. These two steps could take place in different cranks. Since step 1 is essentially just internal bookkeeping, it need not participate in escalator scheduling but rather could just be treated as constant cost overhead, while step 2, which actually results in user code being executed, could be scheduled using the escalator.
What is the Problem Being Solved?
Cyclic promise resolutions interfere with our desired "retire upon resolution" pattern (#1124). To overcome this, @FUDCo has been working on batched resolutions: a single
dispatch.notify()
crank resolves multiple promises at the same time, so they can all be deserialized before any of the identifiers are retired. This has an ordering side-effect: the secondary promises get resolved earlier than they would have otherwise (our current scheduler is straight FIFO).It occurred to me to think about how this will interact with the escalator schedulers. Resolution notifications can cause just as much work as a message delivery, so we want the notifications to travel on escalators just like deliveries. However if we're resolving multiple promises in a single notification, which escalator should it use? The simplest answer is to use the first promise in the batch (the one which was resolved first, and which dragged in all the others).
With an escalator-based scheduler, this changes the ordering side-effect somewhat: the secondary promises might get resolved earlier or later than they would have otherwise. Whoever is paying for the primary notification will also wind up paying for the secondaries. The secondary might get higher priority than they paid for, or they might pay for higher priority but not get it because the primary isn't paying for it.
Potential Solutions
Other than accepting the scheduling side-effect, I can think of a few possible answers:
retire()
message (something likedropImport
, which would probably overlap with the GC/deallocation work). Each notification would travel its own escalator as usual, and be delivered exactly when its payment says so. The kernel would need to keep track of all the resolution notifications whose data references each other, and defer retiring the identifiers until all the notifications made it past the escalators and get delivered. This sounds even more complex, but probably solves the full problem.cc @erights @dtribble
The text was updated successfully, but these errors were encountered: