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

refactor(swingset): improve vat deliveries #4716

Merged
merged 2 commits into from
Mar 3, 2022

Conversation

warner
Copy link
Member

@warner warner commented Mar 2, 2022

This moves some logic out of deliverAndLogToVal and into a higher-level
dispatch function, where it can react to all failure modes in a single place.

We pull "run-queue events" off the run-queue (currently named the "acceptance
queue"). Many of these events are aimed at a specific vat, including 'notify',
but the primary one is 'send' and is aimed at a target, which is either a
kernel object or a kernel promise. For these we use routeSendEvent to
either queue the event on a promise queue, reject it if it can't be
delivered, or deliver it to a specific vat. This is the part that will change
with #3465: in that world, each vat-input-queue exists for a specific vat, so
the routing step moves earlier (into a "routing crank" that pulls events from
a vat-output-queue and possibly adds them to a vat-input-queue).

Some kinds of deliveries care about metering (or don't), and some have
opinions about what should happen if a crank gets unwound. These are now
reported as additional properties in the DeliveryStatus object that is
returned by this delivery path. processDeliveryMessage looks at these
properties, plus the delivery status (if any) to decide what to do at the end
of the crank.

I think most of the behavior should be the same as before. One change is that
the runPolicy will probably get more information about non-'send' cranks
than before (e.g. create-vat might report metering).

This refactoring should make it easier to implement #1848 vat-upgrade, as
well as #3465 queueing changes.

@warner warner added the SwingSet package: SwingSet label Mar 2, 2022
@warner warner self-assigned this Mar 2, 2022
@warner
Copy link
Member Author

warner commented Mar 2, 2022

recommend reviewing with "hide whitespace", to reduce the diff

@warner warner force-pushed the 1848-refactor-deliver-to-vat branch from 13aaf15 to b7fd9a6 Compare March 2, 2022 20:19
@warner warner marked this pull request as ready for review March 2, 2022 20:19
@warner warner requested review from FUDCo and mhofman March 2, 2022 20:19
'xs-worker-no-gc',
].includes(mt),
);
return undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

Won't a function return undefined anyway if you don't have an explicit return statement? Or is this to deal with some kind of TypeScript nonsense?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, typescript

Copy link
Member

Choose a reason for hiding this comment

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

That would be the difference between a return type of void vs undefined.

Copy link
Member Author

Choose a reason for hiding this comment

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

let me know if there's a better way to write that assertion function, I just copied something else that works

Copy link
Member

Choose a reason for hiding this comment

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

Assertions don't require a return value in TS. This might be a case of jsdoc eslint plugin not understanding assertions ?

@warner warner force-pushed the 1848-refactor-deliver-to-vat branch from b7fd9a6 to f0f5f0d Compare March 2, 2022 20:50
Copy link
Contributor

@FUDCo FUDCo left a comment

Choose a reason for hiding this comment

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

This is a very nice blood pressure reducing cleanup! I particularly like getting rid of the output named policyInput which, even though I kinda sorta understood the reasoning behind the name, has always bugged me.

@warner warner force-pushed the 1848-refactor-deliver-to-vat branch from f0f5f0d to 126acf2 Compare March 2, 2022 21:29
Copy link
Member

@mhofman mhofman left a comment

Choose a reason for hiding this comment

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

This looks great! Thanks so much for starting this refactor.

I'm not familiar enough with the termination conditions and the start vat logic to be confident enough in my review for those parts, and I trust @FUDCo on his approval there.

The requested change is for the extension in the import in the types file, in case that file ever ends up actually imported by ES code someday. Rest is mostly nits on types and consistency.

packages/SwingSet/src/kernel/kernel.js Show resolved Hide resolved
'xs-worker-no-gc',
].includes(mt),
);
return undefined;
Copy link
Member

Choose a reason for hiding this comment

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

Assertions don't require a return value in TS. This might be a case of jsdoc eslint plugin not understanding assertions ?

Comment on lines 327 to 330
/**
*
* @returns { ManagerType }
*/
Copy link
Member

Choose a reason for hiding this comment

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

FYI this should be unnecessary given that mt should be typed correctly after the assertion.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can remove the @returns { ManagerType }, thanks. (I started from kernel.js that calls this, added the @returns so the options.managerType = kernelKeeper.getDefaultManagerType() didn't complain, and then added the assertion to make the @returns { ManagerType } shut up.. should have started with the assertion).

If I remove the return undefined; from insistManagerType(), I get this warning:

$ eslint '**/*.js'

/home/warner/stuff/agoric/agoric-sdk/packages/SwingSet/src/kernel/state/kernelKeeper.js
  310:3  warning  JSDoc @returns declaration present but return expression not available in function  jsdoc/require-returns-check

I don't know how to make that go away, so I'm inclined to leave the return undefined;, but if you know a way, I'll apply it.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah sounds like a limitation of the JSDoc eslint plugin, not a problem with typescript. Besides an ugly eslint disable.

An alternative might be to return mt instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

return mt; gets me Type 'string' is not assignable to type 'void. I don't know how to express "returns $type and also asserts that the input value is $type".

packages/SwingSet/src/types-internal.js Outdated Show resolved Hide resolved
packages/SwingSet/src/types-internal.js Show resolved Hide resolved
* @typedef { { meterID?: MeterID } } HasMeterID
* @typedef { import('./types-exported.js').DynamicVatOptionsWithoutMeter } DynamicVatOptionsWithoutMeter
*
* vatKeeper.setSourceAndOptions(source, RecordedVatOptions)
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 seem out of place.

Copy link
Member Author

Choose a reason for hiding this comment

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

it was a reminder of where RecordedVatOptions gets used.. is there a better way to do comments within JSDoc comments? I could use * // vatKeeper.set... maybe.

packages/SwingSet/src/kernel/kernel.js Outdated Show resolved Hide resolved
packages/SwingSet/src/kernel/kernel.js Show resolved Hide resolved
packages/SwingSet/src/kernel/kernel.js Outdated Show resolved Hide resolved
@warner warner force-pushed the 1848-refactor-deliver-to-vat branch from 56fb177 to a946352 Compare March 3, 2022 00:43
@warner warner requested a review from mhofman March 3, 2022 01:03
Comment on lines +282 to +283
// `vatFatalSyscall`. We'd still need a way for `requestTermination` to
// work, though.
Copy link
Member

Choose a reason for hiding this comment

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

Note to self: could this be handled a similar way, something in the vat translation layer that remembers the exit call?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, you know, we should consider making the syscall.exit handler just push an terminate-vat event onto the vat's own input-queue, and perform the teardown later. Sort of "please shut me down, eventually, when it's convenient". Then vat-manager or the translation layer doesn't need to remember anything. And if our scheduler's policy always drains the vat-output-queue before looking at the vat-input-queue, then this would automatically deliver all the previously-emitted work before shutdown, which might line up nicely with our plans around involuntary termination needing to not interfere with previous output, and might simplify the "vat is dead but queues are not" question.

I don't know enough about our use cases for this to know whether promptness is important to us. Maybe it'd be when a contract has finished transferring all its assets and obligations to a successor, and it self-destructs to free up chain capacity, and to prevent surprises when people try to talk to the old one by mistake? Seems like the vat would know that it's in this state, so it could maybe reject all attempts to start new work while waiting to be terminated. OTOH, it would be really annoying to have to add extra "am I active" checks in vat code to make up for the platform not being able to respond to a syscall.exit promptly. We might work around this by configuring the input scheduler to service terminate-vat events ahead of anything else (but still behind draining the output queue).

@@ -0,0 +1,17 @@
import './types.js';
import './types-exported.js';
Copy link
Member

Choose a reason for hiding this comment

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

I'm surprised we still need the exported one.

* // used by vatKeeper.setSourceAndOptions(source, RecordedVatOptions)
*
* @typedef { DynamicVatOptionsWithoutMeter & HasMeterID } InternalDynamicVatOptions
* @typedef { StaticVatOptions | { InternalDynamicVatOptions & HasMeterID } } RecordedVatOptions
Copy link
Member

Choose a reason for hiding this comment

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

I'm confused why this doesn't require a import('./types-exported.js').StaticVatOptions

warner and others added 2 commits March 3, 2022 13:35
This moves some logic out of `deliverAndLogToVal` and into a higher-level
dispatch function, where it can react to all failure modes in a single place.

We pull "run-queue events" off the run-queue (currently named the "acceptance
queue". Many of these events are aimed at a specific vat, including 'notify',
but the primary one is 'send' and is aimed at a *target* kref, which is
either a kernel object or a kernel promise. For these we use `routeSendEvent`
to either queue the event on a promise queue, reject it if it can't be
delivered, or deliver it to a specific vat. This is the part that will change
with #3465: in that world, each vat-input-queue exists for a specific vat, so
the routing step moves earlier (into a "routing crank" that pulls events from
a vat-output-queue and possibly adds them to a vat-input-queue).

Some kinds of deliveries care about metering (or don't), and some have
opinions about what should happen if a crank gets unwound. These are now
reported as additional properties in the DeliveryStatus object that is
returned by this delivery path. `processDeliveryMessage` looks at these
properties, plus the delivery status (if any) to decide what to do at the end
of the crank.

I think most of the behavior should be the same as before. One change is that
the `runPolicy` will probably get more information about non-'send' cranks
than before (e.g. `create-vat` might report metering).

This refactoring should make it easier to implement #1848 vat-upgrade, as
well as #3465 queueing changes.

closes #4687
Add "re-exporting" ambient file for backwards compatibility
@warner warner force-pushed the 1848-refactor-deliver-to-vat branch from 996ad6b to f62335a Compare March 3, 2022 22:11
@warner warner added the automerge:rebase Automatically rebase updates, then merge label Mar 3, 2022
@mergify mergify bot merged commit 57abfe3 into master Mar 3, 2022
@mergify mergify bot deleted the 1848-refactor-deliver-to-vat branch March 3, 2022 22:29
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 SwingSet package: SwingSet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants