Skip to content

Commit

Permalink
refactor(daemon): Synchronize makeGuest (merge #2120)
Browse files Browse the repository at this point in the history
Progresses: #2086

Synchronizes the host's makeGuest() and its dependencies. See #2086 for details.
  • Loading branch information
rekmarks authored Mar 8, 2024
2 parents 37b17ee + f546680 commit d007e19
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 118 deletions.
104 changes: 66 additions & 38 deletions packages/daemon/src/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -896,10 +896,14 @@ const makeDaemonCore = async (
};

/**
* @type {import('./types.js').DaemonCore['incarnateHandle']}
* Incarnates a `handle` formula and synchronously adds it to the formula graph.
* The returned promise is resolved after the formula is persisted.
*
* @param {string} formulaNumber - The formula number of the handle to incarnate.
* @param {string} targetFormulaIdentifier - The formula identifier of the handle's target.
* @returns {import('./types.js').IncarnateResult<import('./types.js').ExternalHandle>} The incarnated handle.
*/
const incarnateHandle = async targetFormulaIdentifier => {
const formulaNumber = await randomHex512();
const incarnateNumberedHandle = (formulaNumber, targetFormulaIdentifier) => {
/** @type {import('./types.js').HandleFormula} */
const formula = {
type: 'handle',
Expand All @@ -911,10 +915,13 @@ const makeDaemonCore = async (
};

/**
* @type {import('./types.js').DaemonCore['incarnatePetStore']}
* Incarnates a `pet-store` formula and synchronously adds it to the formula graph.
* The returned promise is resolved after the formula is persisted.
*
* @param {string} formulaNumber - The formula number of the pet store to incarnate.
* @returns {import('./types.js').IncarnateResult<import('./types.js').PetStore>} The incarnated pet store.
*/
const incarnatePetStore = async specifiedFormulaNumber => {
const formulaNumber = specifiedFormulaNumber ?? (await randomHex512());
const incarnateNumberedPetStore = async formulaNumber => {
/** @type {import('./types.js').PetStoreFormula} */
const formula = {
type: 'pet-store',
Expand All @@ -929,7 +936,7 @@ const makeDaemonCore = async (
*/
const incarnateDirectory = async () => {
const { formulaIdentifier: petStoreFormulaIdentifier } =
await incarnatePetStore();
await incarnateNumberedPetStore(await randomHex512());
const formulaNumber = await randomHex512();
/** @type {import('./types.js').DirectoryFormula} */
const formula = {
Expand All @@ -941,25 +948,12 @@ const makeDaemonCore = async (
);
};

/**
* @type {import('./types.js').DaemonCore['incarnateWorker']}
*/
const incarnateWorker = async () => {
const formulaNumber = await randomHex512();
/** @type {import('./types.js').WorkerFormula} */
const formula = {
type: 'worker',
};
return /** @type {import('./types').IncarnateResult<import('./types').EndoWorker>} */ (
provideValueForNumberedFormula(formula.type, formulaNumber, formula)
);
};

/**
* Incarnates a `worker` formula and synchronously adds it to the formula graph.
* The returned promise is resolved after the formula is persisted.
*
* @param {string} formulaNumber - The worker formula number.
* @returns {Promise<{ formulaIdentifier: string, value: import('./types').EndoWorker }>}
* @returns {ReturnType<import('./types.js').DaemonCore['incarnateWorker']>}
*/
const incarnateNumberedWorker = formulaNumber => {
/** @type {import('./types.js').WorkerFormula} */
Expand All @@ -972,6 +966,14 @@ const makeDaemonCore = async (
);
};

/**
* @type {import('./types.js').DaemonCore['incarnateWorker']}
*/
const incarnateWorker = async () => {
const formulaNumber = await formulaGraphMutex.enqueue(randomHex512);
return incarnateNumberedWorker(formulaNumber);
};

/** @type {import('./types.js').DaemonCore['incarnateHost']} */
const incarnateHost = async (
endoFormulaIdentifier,
Expand All @@ -983,10 +985,10 @@ const makeDaemonCore = async (
let workerFormulaIdentifier = specifiedWorkerFormulaIdentifier;
if (workerFormulaIdentifier === undefined) {
({ formulaIdentifier: workerFormulaIdentifier } =
await incarnateWorker());
await incarnateNumberedWorker(await randomHex512()));
}
const { formulaIdentifier: storeFormulaIdentifier } =
await incarnatePetStore();
await incarnateNumberedPetStore(await randomHex512());
const { formulaIdentifier: inspectorFormulaIdentifier } =
// eslint-disable-next-line no-use-before-define
await incarnatePetInspector(storeFormulaIdentifier);
Expand All @@ -1006,12 +1008,41 @@ const makeDaemonCore = async (
};

/** @type {import('./types.js').DaemonCore['incarnateGuest']} */
const incarnateGuest = async hostHandleFormulaIdentifier => {
const formulaNumber = await randomHex512();
const { formulaIdentifier: storeFormulaIdentifier } =
await incarnatePetStore();
const { formulaIdentifier: workerFormulaIdentifier } =
await incarnateWorker();
const incarnateGuest = async (hostFormulaIdentifier, deferredTasks) => {
const {
guestFormulaNumber,
hostHandleFormulaIdentifier,
storeFormulaIdentifier,
workerFormulaIdentifier,
} = await formulaGraphMutex.enqueue(async () => {
const formulaNumber = await randomHex512();
const hostHandle = await incarnateNumberedHandle(
await randomHex512(),
hostFormulaIdentifier,
);
const storeIncarnation = await incarnateNumberedPetStore(
await randomHex512(),
);
const workerIncarnation = await incarnateNumberedWorker(
await randomHex512(),
);

await deferredTasks.execute({
guestFormulaIdentifier: serializeFormulaIdentifier({
type: 'guest',
number: formulaNumber,
node: ownNodeIdentifier,
}),
});

return harden({
guestFormulaNumber: formulaNumber,
hostHandleFormulaIdentifier: hostHandle.formulaIdentifier,
storeFormulaIdentifier: storeIncarnation.formulaIdentifier,
workerFormulaIdentifier: workerIncarnation.formulaIdentifier,
});
});

/** @type {import('./types.js').GuestFormula} */
const formula = {
type: 'guest',
Expand All @@ -1020,7 +1051,7 @@ const makeDaemonCore = async (
worker: workerFormulaIdentifier,
};
return /** @type {import('./types').IncarnateResult<import('./types').EndoGuest>} */ (
provideValueForNumberedFormula(formula.type, formulaNumber, formula)
provideValueForNumberedFormula(formula.type, guestFormulaNumber, formula)
);
};

Expand All @@ -1030,7 +1061,7 @@ const makeDaemonCore = async (
source,
codeNames,
endowmentFormulaIdsOrPaths,
hooks,
deferredTasks,
specifiedWorkerFormulaIdentifier,
) => {
const {
Expand Down Expand Up @@ -1073,7 +1104,7 @@ const makeDaemonCore = async (
evalFormulaIdentifier: ownFormulaIdentifier,
});

await Promise.all(hooks.map(hook => hook(identifiers)));
await deferredTasks.execute(identifiers);
return identifiers;
});

Expand Down Expand Up @@ -1265,13 +1296,13 @@ const makeDaemonCore = async (
});

const { formulaIdentifier: defaultHostWorkerFormulaIdentifier } =
await incarnateWorker();
await incarnateNumberedWorker(await randomHex512());
const { formulaIdentifier: networksDirectoryFormulaIdentifier } =
await incarnateNetworksDirectory();
const { formulaIdentifier: leastAuthorityFormulaIdentifier } =
await incarnateLeastAuthority();
const { formulaIdentifier: newPeersFormulaIdentifier } =
await incarnatePetStore(peersFormulaNumber);
await incarnateNumberedPetStore(peersFormulaNumber);
if (newPeersFormulaIdentifier !== peersFormulaIdentifier) {
throw new Error(
`Peers PetStore formula identifier did not match expected value.`,
Expand Down Expand Up @@ -1444,7 +1475,6 @@ const makeDaemonCore = async (
incarnateUnconfined,
incarnateBundle,
incarnateWebBundle,
incarnateHandle,
storeReaderRef,
makeMailbox,
makeDirectoryNode,
Expand Down Expand Up @@ -1597,8 +1627,6 @@ const makeDaemonCore = async (
incarnateLeastAuthority,
incarnateNetworksDirectory,
incarnateLoopbackNetwork,
incarnateHandle,
incarnatePetStore,
incarnateDirectory,
incarnateWorker,
incarnateHost,
Expand Down
16 changes: 16 additions & 0 deletions packages/daemon/src/deferred-tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @returns {import('./types.js').DeferredTasks<any>}
*/
export const makeDeferredTasks = () => {
/** @type {import('./types.js').DeferredTask<any>[]} */
const tasks = [];

return {
execute: async param => {
await Promise.all(tasks.map(task => task(param)));
},
push: task => {
tasks.push(task);
},
};
};
Loading

0 comments on commit d007e19

Please sign in to comment.