-
Notifications
You must be signed in to change notification settings - Fork 207
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 dispatch to be a function, not an object #2674
Conversation
Can anyone help me with the type annotations? https://github.com/Agoric/agoric-sdk/pull/2674/checks?check_run_id=2137783731#step:7:98 says that
is unhappy because |
packages/SwingSet/src/kernel/vatManager/manager-subprocess-xsnap.js
Outdated
Show resolved
Hide resolved
87fb514
to
89e1324
Compare
64a967b
to
93e7e7f
Compare
89e1324
to
9214adf
Compare
This does a number of other cleanups and refactorings to align the four different worker types. The overall diff is kind of big, but each individual commit is pretty small and self-contained, so I'd recommend reviewing each commit separately and sequentially. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* | ||
* @typedef { [tag: 'message', target: string, msg: Message]} VatDeliveryMessage | ||
* @typedef { [tag: 'notify', resolutions: string[] ]} VatDeliveryNotify | ||
* @typedef { [tag: 'dropExports', vrefs: string[] ]} VatDeliveryDropExports |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay! types! but...
Names such as VatDeliveryDropExports
don't seem to get reused anywhere. I suspect the VatDeliveryObject
and VatSyscallObject
types would be more clear if the options were inlined.
minor style issue. not critical.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't know how to do that. Would it be something like:
/**
* @typedef { [tag: 'message', target: string, msg: Message] |
* [tag: 'notify', resolutions: string[]] |
* [tag: 'dropExports', vrefs: string[]] } VatDeliveryObject
*/
?
(note to self/chip, that notify
signature isn't correct, I'll fix that)
At some point soon, we're going to have a function in liveslots which switches on tag
and then calls one of three different functions. Would the typedefs on those three functions be a reason to retain the VatDeliveryMessage
/etc subtypes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be something like: ... ?
yes.
Would the typedefs on those three functions be a reason to retain the VatDeliveryMessage/etc subtypes?
yes.
import { assert, details as X } from '@agoric/assert'; | ||
import { insistMessage } from '../../message'; | ||
/** @type { (delivery: VatDeliveryObject, prefix: string) => string } */ | ||
function summarizeDelivery(vatDeliveryObject, prefix = 'vat') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strange name for something that always returns a ... failed
message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's really a "make a message to log just in case it fails" function, but that name seemed expedient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
failureMessage
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
summarizeDeliveryFailure
maybe?
const dispatchArgs = dispatchRecord.slice(1); | ||
transcriptManager.startDispatch(dispatchRecord); | ||
await runAndWait(() => dispatch[dispatchOp](...dispatchArgs), errmsg); | ||
// vatDeliveryObject is one of: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to keep this comment here? It duplicates a lot of info that's now in types; move the prose to the type declaration? Also: cite the .md
doc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree. Keep the prose here. It's more informative and more legible than the type declaration.
return doProcess(['dropExports', vrefs], errmsg); | ||
} | ||
|
||
// vatDeliverObject is: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
likewise... move prose to type declaration and remove?
workerLog(`doProcess done`); | ||
/** @type { Tagged } */ | ||
const vatDeliveryResults = harden(['ok']); | ||
return vatDeliveryResults; | ||
} | ||
|
||
/** @type { (ts: unknown, msg: any) => Promise<Tagged> } */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yay! deleting code!
const slot = args.slots[qnode.index]; | ||
insistVatType('device', slot); | ||
function dispatch(vatDeliverObject) { | ||
const { method, args } = extractMessage(vatDeliverObject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reads nicely.
return [[promiseID, rejected, data]]; | ||
} | ||
|
||
function buildSyscall() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah... so we had already written buildSyscall()
but not exported it. Cool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah there are a bunch of little helpers in various tests that finally hit my threshold for factoring them out into something common
93e7e7f
to
bac7b20
Compare
35c67dc
to
b96c1f7
Compare
9ba29cb
to
aefc80d
Compare
b96c1f7
to
4eeea9a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine. Getting rid of some of the extraneous, additional, and unnecessary redundancy and duplication is especially good.
You can probably expect some minor complications merging test-comms.js
.
const dispatchArgs = dispatchRecord.slice(1); | ||
transcriptManager.startDispatch(dispatchRecord); | ||
await runAndWait(() => dispatch[dispatchOp](...dispatchArgs), errmsg); | ||
// vatDeliveryObject is one of: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree. Keep the prose here. It's more informative and more legible than the type declaration.
import { assert, details as X } from '@agoric/assert'; | ||
import { insistMessage } from '../../message'; | ||
/** @type { (delivery: VatDeliveryObject, prefix: string) => string } */ | ||
function summarizeDelivery(vatDeliveryObject, prefix = 'vat') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
summarizeDeliveryFailure
maybe?
assert( | ||
dispatch && dispatch.deliver, | ||
`vat failed to return a 'dispatch' with .deliver: ${dispatch}`, | ||
assert.equal( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason here not to use assert.typeof
?
0a60719
to
8fe8077
Compare
4eeea9a
to
2c97e63
Compare
This was a false start on the GC task. Previously we thought vat-side finalizers would call a vat-specific `decref` function at spontaneous times, and the kernel would accumulate the dropped references for later processing. Now we have liveslots collect the finalizer results and perform a non-transcript-enforced syscall.dropImports at the end of crank. This removes `testTrackDecref` from `kernelOptions`.
This changes the protocol used to speak to the three remote vat workers (nodeworker, subprocess-node, subprocess-xsnap) slightly. Previously we unpacked the VatSyscallObject (a tagged array of `[syscallTag, ...syscallArgs]`) when constructing a remote message (which has its own tag), giving us something like `['syscall', syscallTag, ...syscallArgs]`. Now we leave the VatSyscallObject intact, giving us `['syscall', [syscallTag, ...syscallArgs]]`. This should be a bit simpler. It changes the protocol in an incompatible way, but the child thread/process never outlives the kernel process, so the incompatibility shouldn't be observable.
message.js acquired insistVatDeliveryObject() and insistVatSyscallObject(), which are type guard functions that match. Also rename CapDataS to SwingSetCapData.
This changes the protocol used to speak to the three remote vat workers (nodeworker, subprocess-node, subprocess-xsnap) slightly, by leaving the VatDeliveryObject intact (rather than merging it with the outer frame). This object starts each crank by either delivering a 'message', a 'notify', or a 'dropExports' operation.
This changes the protocol used to speak to two of the remote vat workers (nodeworker, subprocess-node) slightly, by leaving the VatDeliveryResults intact (rather than merging it with the outer frame). The subprocess-xsnap protocol has its own return-value framing and wasn't merging this object into it.
These two worker types were lagging behind the others, and weren't recording dispatches into their transcripts. Any vats using them would fail to replay after a host restart, because their transcripts would be empty.
Previously, the lowest level of a vat was defined by an object named `dispatch`, which had three methods: `{ deliver, notify, dropExports }`. Now we define `dispatch()` to be a *function*, which takes a `VatDeliveryObject` (of which there are three flavors). This simplifies the supervisor code and removes a lot of redundant boilerplate, and prepares for later phase where `dispatch()` becomes `async dispatch()`. refs #2671
2c97e63
to
692c7d6
Compare
Alas this is based upon PR #2667 (the I'm going to have to re-do the refactorings without the WeakRef tracking. It will be shaped a lot like this branch, but it won't be this branch, and it won't target |
Previously, the low-level vat interface was defined by a
dispatch
object,with methods like
.deliver
and.notify
. Now, it is defined by adispatch()
function, which takes avatDeliveryObject
that has the exactsame form as the data sent in the kernel-vat protocol.
This reduces the size of the manager/supervisor code and reduces the
redundancy somewhat.
refs #2671