-
Notifications
You must be signed in to change notification settings - Fork 208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Notifier observers to discriminate between vat failure and upgrade #5185
Comments
This overlaps with SwingSet because that's where vat failure-vs-upgrade originates. But the protocol definition and implementation is squarely in |
What I just heard from @FUDCo is that @erights agreed to use |
I'm ok with that as long as it's documented somewhere, preferably including at the place where the string is thrown. As I mentioned in the PR, I believe we should have a single const where the special string is defined, with a comment explaining why it's so, and that it must not change without an update to code relying on notifiers. |
I also would prefer if notifiers used a helper like |
Something like that would be good, but not with that name. As @erights points out, the reason for not using an Error is that it's not an error. |
Also, if we had used |
@gibson042 to modify the two client-side helper functions in @dtribble says: if the first request to this notifier rejects with the "vat upgraded", that's probably a deeper error, and we should stop. @erights says what? @dtribble says: if you didn't get the promise yourself...
But: if the promise actually gets rejected (with @erights says: rejected promise contagion can confuse. Maybe getting a rejection reason through contagion is an error. |
The rest of the post below is of historical interest only. While writing it up, I realized that it is fatally flawed, which I'll explain in the next message.
The rest of the post above is of historical interest only. While writing it up, I realized that it is fatally flawed, which I'll explain in the next message. |
The fatal problem is that blind rejection reason contagion is too deeply a part of existing standard JavaScript semantics that we absolutely cannot change. Consider |
First, I thought that when sending a message to an errored promise, the resulting error was already a new error generated either by Swingset or liveslots/HandledPromise? Second, I thought @dtribble's point was that the update result of Edit: sorry I am wholly unfamiliar with our notifiers. |
From my perspective, this is the promise transitioning to a "disconnected" state. But that's not worth trying to make a distinct state in the promise. Instead, make the rejection distinct: make a unique Disconnection object that represents this disconnection event, or have it be a record with a unique value. Then, a client that makes a retry can tell if that retry fails as a result of the same disconnection event. This is pretty simple, easy to understand, and solves the retry problem. If you can use object identity here, then it doesn't require any unique data. Otherwise, it might require a kernel-provided data value. |
Ah so mint a brand new object with identity and reject promises of that specific upgrade with that. If the client tries twice and gets that unique object twice as rejection in a row, consider that the notifier is permanently borked? For identification purposes, we could wrap the unique object in copy data, e.g. |
When you send/then to a rejected promise, the result is a promise rejected with exactly the same rejection value, not a newly generated thing.
The result of
So this is not about the notifier value at all. The result of |
Yep. Unless of course the object identity doesn't propagate usefully across boundaries. I had long ago propose an extension for that, but having it be a presence for the upgrade event would work. Or unique data. |
I do not like the idea that |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
I have moved the conversation about rejection contagion in eventual-send to endojs/endo#1176 |
Requiring that precludes tail recursion optimization because each layer must be prepared to wrap a failure with more information. |
@dtribble is that comment related to notifiers, or to the broader question of rejection contagion? |
It certainly is a valid counterargument against wrapping during rejection contagion. Good catch! |
I'd prefer discussing the rejection contagion in endojs/endo#1176, but I don't see how tail recursion causes any issue. You can always redirect the result promise of the delivery to the result promise of the tail send. We're only talking about wrapping an error in the resolution of the send target, not the whole send. Equivalent userland code, which can be tail-optimized in the kernel: const applyMethod = async (x, p, args) =>
E.when(
x,
(r) => r[p](...args),
(e) => Promise.reject(new Error(`Cannot call ${p} on rejection`, { cause: e })),
); |
I believe @dtribble doesn't mean literal tail recursion, but rather the accumulation of storage proportional to the depth of the recursion. If Alice says const p = E(bob).foo(carol); invoking Bob's foo: carol => E(carol).bar(); then currently, the promise for the result of @dtribble am I representing your concern accurately? |
@dtribble @erights answered at endojs/endo#1176 (comment) |
Please coordinate with #5649 , which will change the upgrade-provoked rejection value to be a distinctive object (not an Error). |
…grade subscribeEach iterators continue to fail in that scenario, because they cannot guarantee absence of gaps. Fixes #5185
…grade subscribeEach iterators continue to fail in that scenario, because they cannot guarantee absence of gaps. Fixes #5185
Some interesting questions are being raised by the current state of #7401:
|
Number 1 looks good. ISTR the As far as 2, I like your suggestion: we can and should "commit to |
…grade subscribeEach iterators continue to fail in that scenario, because they cannot guarantee absence of gaps. Fixes #5185
…grade subscribeEach iterators continue to fail in that scenario, because they cannot guarantee absence of gaps. Fixes #5185
What is the Problem Being Solved?
We need a mechanism for notifier observers to discern a failure caused by a vat termination (which should result in a permanent failure), and a failure caused by a vat upgrade (which should result in a retry).
By happen-chance right now we're been using an error instance for the former, and an error string for the latter. This is however very brittle, and a drive-by change (almost?) made the string an error: https://github.com/Agoric/agoric-sdk/pull/5130/files#r854732408
Description of the Design
Some more stable and documented way to discern the cause of failure, and whether a retry should be attempted.
Security Considerations
Test Plan
There must be tests and documentation for this behavior.
The text was updated successfully, but these errors were encountered: