Open warner opened 3 years ago
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