Skip to content
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

smart wallet report rejections of durable promises #8998

Merged
merged 4 commits into from
Feb 27, 2024
Merged

Conversation

turadg
Copy link
Member

@turadg turadg commented Feb 26, 2024

closes: #8997

Description

This moves the error handling into an onRejected callback of the durable promise watcher for the offer result. The other two watchers are for particular values from Zoe after that promise resolves. Those are synchronous and don't need their own error handling.

It doesn't move tryReclaimingWithdrawnPayments because that would require heavier refactoring and in our analysis its a very unlikely scenario. I've commented with why it's there. I also changed its return type to Promise<void>, instead of all the settlements. Since that value was never read, it's not changing behavior and I called it a refactor.

Security Considerations

No change.

Scaling Considerations

No change.

Documentation Considerations

It would help if Zoe documented in its code which methods' promises settle together.

Testing Considerations

Ideally there'd be a new test for this fix but there isn't.

Upgrade Considerations

To be included in u14 upgrade of smartWallet.

Comment on lines 1011 to 1025
if (offerSpec?.proposal?.give) {
facets.payments
.tryReclaimingWithdrawnPayments(offerSpec.id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we assume this case only matters for immediate rejections from the seat?

I suppose that tryReclaimingWithdrawnPayments is not very idempotent, nor parallel safe.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"parallel"?

Noting that at #8488 I see

along the way payments.tryReclaimingWithdrawnPayments() went away. I'm pretty sure it was redundant with ERTP recoverySets.

@@ -186,6 +193,17 @@ export const prepareOfferWatcher = baggage => {
facets.helper.updateStatus({ result: UNPUBLISHED_RESULT });
}
},
/** @param {Error} err */
handleError(err) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment this will likely be called multiple times (aka it needs to handle parallels duplicate calls)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get "parallel". Did you mean just "handle duplicate calls?"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be duplicate call, and since the async operation this initiates is not awaited, they will overlap

@mhofman
Copy link
Member

mhofman commented Feb 27, 2024

there may be unique error messages.

To be honest, while it's technically possible for a vstorage client to recover each of these errors, it's painful as the same field is updated, likely in the same block.

Copy link
Contributor

@Chris-Hibbert Chris-Hibbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's any value in reporting the errors 4 times. The different promises are all triggered on the same Zoe promise. If they fail independently, something is deeply wrong and having multiple watchers won't help.

I would drop the watcher in the original catch clause, as well as two of the three in offerWatcher. My nominee to keep would be resultWatcher, mostly because it sounds like it's at a high semantic level.

@@ -186,6 +193,17 @@ export const prepareOfferWatcher = baggage => {
facets.helper.updateStatus({ result: UNPUBLISHED_RESULT });
}
},
/** @param {Error} err */
handleError(err) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get "parallel". Did you mean just "handle duplicate calls?"

@@ -209,6 +227,8 @@ export const prepareOfferWatcher = baggage => {
const { facets } = this;
if (isUpgradeDisconnection(err)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line makes clear that the type of err must include UpgradeDisconnection. So probably Error | UpgradeDisconnection. Likewise elsewhere. The guards for all of these are fine though, since they say only M.any().

Comment on lines 1011 to 1025
if (offerSpec?.proposal?.give) {
facets.payments
.tryReclaimingWithdrawnPayments(offerSpec.id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"parallel"?

Noting that at #8488 I see

along the way payments.tryReclaimingWithdrawnPayments() went away. I'm pretty sure it was redundant with ERTP recoverySets.

Copy link
Member

@erights erights left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Chris-Hibbert and I walked through this verbally. LGTM!

We talked over the redundant errors being logged to vstorage. I think this is fine for now. The annoyance is minor, and I don't want to make further code changes at the last minute that we do not need.


// Notify the user
// Update status to observers
if (err.upgradeMessage === 'vat upgraded') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Chris-Hibbert I just checked again, and this is the only non-test check manually using upgradeMessage rather than the isUpgradeDisconnection. I'm satisfied enough at our analysis that this is harmless to request it in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@turadg, since you're still making changes, would you mind updating this?

Suggested change
if (err.upgradeMessage === 'vat upgraded') {
if (isUpgradeDisconnection(err)) {

Copy link
Member Author

@turadg turadg Feb 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah, I meant to but I don't think it's worth spinning CI at this point

Copy link
Member

@erights erights left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a "request changes" as an interlock, to head off any concurrent attempt to merge. But approving now in case I'm hard to reach. In any case, the one remaining fix I'd like to see isn't crucial anyway. But would be nice.

@turadg turadg requested a review from Chris-Hibbert February 27, 2024 16:26
@turadg turadg marked this pull request as ready for review February 27, 2024 16:31
@turadg turadg added the force:integration Force integration tests to run on PR label Feb 27, 2024
@turadg turadg force-pushed the 8997-error-handling branch from 2b7c4e5 to 4d4c3f7 Compare February 27, 2024 17:25
Comment on lines +197 to +199
* Called when the offer result promise rejects. The other two watchers
* are waiting for particular values out of Zoe but they settle at the same time
* and don't need their own error handling.
Copy link
Member

@gibson042 gibson042 Feb 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Called when the offer result promise rejects. The other two watchers
* are waiting for particular values out of Zoe but they settle at the same time
* and don't need their own error handling.
* Called when the offer result promise rejects. The payment and
* numWantsSatisfied promises settle at the same time and don't need
* their own error handling.

Copy link
Contributor

@Chris-Hibbert Chris-Hibbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I requested a change while approving, and then everyone else approved. I don't want my request to get lost, so I'm changing my review status again.

And in the meantime, I requested another (very small) change.

@turadg turadg added the automerge:rebase Automatically rebase updates, then merge label Feb 27, 2024
Copy link
Contributor

@Chris-Hibbert Chris-Hibbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. LGTM.

@mergify mergify bot merged commit 6676107 into master Feb 27, 2024
74 checks passed
@mergify mergify bot deleted the 8997-error-handling branch February 27, 2024 18:40
@mhofman
Copy link
Member

mhofman commented Feb 27, 2024

Did this merge without new commits being pushed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge:rebase Automatically rebase updates, then merge force:integration Force integration tests to run on PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

refactor smartWallet error handling on executeOffer
5 participants