Skip to content

Commit

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

Synchronizes the host's `makeBundle()` following the pattern established by `makeUnconfined()`. Eliminates the host's
`provideWorkerFormulaIdentifier()`, which is everywhere replaced with the synchronous `prepareWorkerFormulaIdentifier()`. Performs some opportunistic refactors of `makeX` and `incarnateX` where `X === 'Bundle' | 'Unconfined'`.
  • Loading branch information
rekmarks authored Mar 9, 2024
2 parents 96e54b9 + eb82858 commit d90350c
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 114 deletions.
4 changes: 3 additions & 1 deletion packages/cli/src/pet-name.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const { quote: q } = assert;

/**
* Splits a dot-delimited pet name path into an array of pet names.
* Throws if any of the path segments are empty.
Expand All @@ -10,7 +12,7 @@ export const parsePetNamePath = petNamePath => {
for (const petName of petNames) {
if (petName === '') {
throw new Error(
`Pet name path "${petNamePath}" contains an empty segment.`,
`Pet name path ${q(petNamePath)} contains an empty segment.`,
);
}
}
Expand Down
141 changes: 93 additions & 48 deletions packages/daemon/src/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,19 @@ const makeDaemonCore = async (
);
};

/** @type {import('./types.js').DaemonCore['incarnateReadableBlob']} */
const incarnateReadableBlob = async contentSha512 => {
const formulaNumber = await randomHex512();
/** @type {import('./types.js').ReadableBlobFormula} */
const formula = {
type: 'readable-blob',
content: contentSha512,
};
return /** @type {import('./types.js').IncarnateResult<import('./types.js').FarEndoReadable>} */ (
provideValueForNumberedFormula(formula.type, formulaNumber, formula)
);
};

/**
* Incarnates a `handle` formula and synchronously adds it to the formula graph.
* The returned promise is resolved after the formula is persisted.
Expand Down Expand Up @@ -1201,6 +1214,41 @@ const makeDaemonCore = async (
return guestIncarnation.formulaIdentifier;
};

/**
* Helper for `incarnateUnconfined` and `incarnateBundle`.
* @param {'make-bundle' | 'make-unconfined'} formulaType
* @param {string} hostFormulaIdentifier
* @param {import('./types.js').DeferredTasks<import('./types.js').MakeCapletDeferredTaskParams>} deferredTasks
* @param {string} [specifiedWorkerFormulaIdentifier]
* @param {string} [specifiedPowersFormulaIdentifier]
*/
const incarnateCapletDependencies = async (
formulaType,
hostFormulaIdentifier,
deferredTasks,
specifiedWorkerFormulaIdentifier,
specifiedPowersFormulaIdentifier,
) => {
const ownFormulaNumber = await randomHex512();
const identifiers = harden({
powersFormulaIdentifier: await providePowersFormulaIdentifier(
hostFormulaIdentifier,
specifiedPowersFormulaIdentifier,
),
capletFormulaIdentifier: serializeFormulaIdentifier({
type: formulaType,
number: ownFormulaNumber,
node: ownNodeIdentifier,
}),
capletFormulaNumber: ownFormulaNumber,
workerFormulaIdentifier: await provideWorkerFormulaIdentifier(
specifiedWorkerFormulaIdentifier,
),
});
await deferredTasks.execute(identifiers);
return identifiers;
};

/** @type {import('./types.js').DaemonCore['incarnateUnconfined']} */
const incarnateUnconfined = async (
hostFormulaIdentifier,
Expand All @@ -1211,28 +1259,17 @@ const makeDaemonCore = async (
) => {
const {
powersFormulaIdentifier,
unconfinedFormulaNumber: formulaNumber,
capletFormulaNumber,
workerFormulaIdentifier,
} = await formulaGraphMutex.enqueue(async () => {
const ownFormulaNumber = await randomHex512();
const identifiers = harden({
powersFormulaIdentifier: await providePowersFormulaIdentifier(
hostFormulaIdentifier,
specifiedPowersFormulaIdentifier,
),
unconfinedFormulaIdentifier: serializeFormulaIdentifier({
type: 'make-unconfined',
number: ownFormulaNumber,
node: ownNodeIdentifier,
}),
unconfinedFormulaNumber: ownFormulaNumber,
workerFormulaIdentifier: await provideWorkerFormulaIdentifier(
specifiedWorkerFormulaIdentifier,
),
});
await deferredTasks.execute(identifiers);
return identifiers;
});
} = await formulaGraphMutex.enqueue(() =>
incarnateCapletDependencies(
'make-unconfined',
hostFormulaIdentifier,
deferredTasks,
specifiedWorkerFormulaIdentifier,
specifiedPowersFormulaIdentifier,
),
);

/** @type {import('./types.js').MakeUnconfinedFormula} */
const formula = {
Expand All @@ -1241,21 +1278,46 @@ const makeDaemonCore = async (
powers: powersFormulaIdentifier,
specifier,
};
return /** @type {import('./types.js').IncarnateResult<unknown>} */ (
provideValueForNumberedFormula(formula.type, formulaNumber, formula)
return provideValueForNumberedFormula(
formula.type,
capletFormulaNumber,
formula,
);
};

/** @type {import('./types.js').DaemonCore['incarnateReadableBlob']} */
const incarnateReadableBlob = async contentSha512 => {
const formulaNumber = await randomHex512();
/** @type {import('./types.js').ReadableBlobFormula} */
/** @type {import('./types.js').DaemonCore['incarnateBundle']} */
const incarnateBundle = async (
hostFormulaIdentifier,
bundleFormulaIdentifier,
deferredTasks,
specifiedWorkerFormulaIdentifier,
specifiedPowersFormulaIdentifier,
) => {
const {
powersFormulaIdentifier,
capletFormulaNumber,
workerFormulaIdentifier,
} = await formulaGraphMutex.enqueue(() =>
incarnateCapletDependencies(
'make-bundle',
hostFormulaIdentifier,
deferredTasks,
specifiedWorkerFormulaIdentifier,
specifiedPowersFormulaIdentifier,
),
);

/** @type {import('./types.js').MakeBundleFormula} */
const formula = {
type: 'readable-blob',
content: contentSha512,
type: 'make-bundle',
worker: workerFormulaIdentifier,
powers: powersFormulaIdentifier,
bundle: bundleFormulaIdentifier,
};
return /** @type {import('./types.js').IncarnateResult<import('./types.js').FarEndoReadable>} */ (
provideValueForNumberedFormula(formula.type, formulaNumber, formula)
return provideValueForNumberedFormula(
formula.type,
capletFormulaNumber,
formula,
);
};

Expand All @@ -1275,23 +1337,6 @@ const makeDaemonCore = async (
return provideValueForNumberedFormula(formula.type, formulaNumber, formula);
};

/** @type {import('./types.js').DaemonCore['incarnateBundle']} */
const incarnateBundle = async (
powersFormulaIdentifier,
workerFormulaIdentifier,
bundleFormulaIdentifier,
) => {
const formulaNumber = await randomHex512();
/** @type {import('./types.js').MakeBundleFormula} */
const formula = {
type: 'make-bundle',
worker: workerFormulaIdentifier,
powers: powersFormulaIdentifier,
bundle: bundleFormulaIdentifier,
};
return provideValueForNumberedFormula(formula.type, formulaNumber, formula);
};

/** @type {import('./types.js').DaemonCore['incarnateWebBundle']} */
const incarnateWebBundle = async (
powersFormulaIdentifier,
Expand Down
88 changes: 35 additions & 53 deletions packages/daemon/src/host.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,35 +223,12 @@ export const makeHostMaker = ({
);
};

/**
* @param {string | 'MAIN' | 'NEW'} workerName
*/
const provideWorkerFormulaIdentifier = async workerName => {
if (workerName === 'MAIN') {
return mainWorkerFormulaIdentifier;
} else if (workerName === 'NEW') {
const { formulaIdentifier: workerFormulaIdentifier } =
await incarnateWorker();
return workerFormulaIdentifier;
}

assertPetName(workerName);
let workerFormulaIdentifier = petStore.identifyLocal(workerName);
if (workerFormulaIdentifier === undefined) {
({ formulaIdentifier: workerFormulaIdentifier } =
await incarnateWorker());
assertPetName(workerName);
await petStore.write(workerName, workerFormulaIdentifier);
}
return workerFormulaIdentifier;
};

/**
* @param {string | 'MAIN' | 'NEW'} workerName
* @param {import('./types.js').DeferredTasks<{ workerFormulaIdentifier: string }>['push']} deferTask
* @returns {string | undefined}
*/
const provideWorkerFormulaIdentifierSync = (workerName, deferTask) => {
const prepareWorkerFormulaIdentifier = (workerName, deferTask) => {
if (workerName === 'MAIN') {
return mainWorkerFormulaIdentifier;
} else if (workerName === 'NEW') {
Expand Down Expand Up @@ -292,7 +269,7 @@ export const makeHostMaker = ({
* @param {import('./types.js').DeferredTasks<{ powersFormulaIdentifier: string }>['push']} deferTask
* @returns {string | undefined}
*/
const providePowersFormulaIdentifierSync = (partyName, deferTask) => {
const preparePowersFormulaIdentifier = (partyName, deferTask) => {
const powersFormulaIdentifier = petStore.identifyLocal(partyName);
if (powersFormulaIdentifier === undefined) {
deferTask(identifiers =>
Expand Down Expand Up @@ -326,7 +303,7 @@ export const makeHostMaker = ({
/** @type {import('./types.js').DeferredTasks<import('./types.js').EvalDeferredTaskParams>} */
const tasks = makeDeferredTasks();

const workerFormulaIdentifier = provideWorkerFormulaIdentifierSync(
const workerFormulaIdentifier = prepareWorkerFormulaIdentifier(
workerName,
tasks.push,
);
Expand Down Expand Up @@ -368,34 +345,47 @@ export const makeHostMaker = ({
return value;
};

/** @type {import('./types.js').EndoHost['makeUnconfined']} */
const makeUnconfined = async (
workerName,
specifier,
powersName,
resultName,
) => {
/**
* Helper function for makeUnconfined and makeBundle.
* @param {string} powersName
* @param {string} workerName
* @param {string} [resultName]
*/
const prepareMakeCaplet = (powersName, workerName, resultName) => {
assertPowersName(powersName);

/** @type {import('./types.js').DeferredTasks<import('./types.js').MakeUnconfinedDeferredTaskParams>} */
/** @type {import('./types.js').DeferredTasks<import('./types.js').MakeCapletDeferredTaskParams>} */
const tasks = makeDeferredTasks();

const workerFormulaIdentifier = provideWorkerFormulaIdentifierSync(
const workerFormulaIdentifier = prepareWorkerFormulaIdentifier(
workerName,
tasks.push,
);

const powersFormulaIdentifier = providePowersFormulaIdentifierSync(
const powersFormulaIdentifier = preparePowersFormulaIdentifier(
powersName,
tasks.push,
);

if (resultName !== undefined) {
tasks.push(identifiers =>
petStore.write(resultName, identifiers.unconfinedFormulaIdentifier),
petStore.write(resultName, identifiers.capletFormulaIdentifier),
);
}

return { tasks, workerFormulaIdentifier, powersFormulaIdentifier };
};

/** @type {import('./types.js').EndoHost['makeUnconfined']} */
const makeUnconfined = async (
workerName,
specifier,
powersName,
resultName,
) => {
const { tasks, workerFormulaIdentifier, powersFormulaIdentifier } =
prepareMakeCaplet(powersName, workerName, resultName);

// Behold, recursion:
// eslint-disable-next-line no-use-before-define
const { value } = await incarnateUnconfined(
Expand All @@ -420,31 +410,23 @@ export const makeHostMaker = ({
powersName,
resultName,
) => {
const workerFormulaIdentifier = await provideWorkerFormulaIdentifier(
workerName,
);

const bundleFormulaIdentifier = petStore.identifyLocal(bundleName);
if (bundleFormulaIdentifier === undefined) {
throw new TypeError(`Unknown pet name for bundle: ${bundleName}`);
throw new TypeError(`Unknown pet name for bundle: ${q(bundleName)}`);
}

const powersFormulaIdentifier = await providePowersFormulaIdentifier(
powersName,
);
const { tasks, workerFormulaIdentifier, powersFormulaIdentifier } =
prepareMakeCaplet(powersName, workerName, resultName);

// Behold, recursion:
// eslint-disable-next-line no-use-before-define
const { value, formulaIdentifier } = await incarnateBundle(
powersFormulaIdentifier,
workerFormulaIdentifier,
const { value } = await incarnateBundle(
hostFormulaIdentifier,
bundleFormulaIdentifier,
tasks,
workerFormulaIdentifier,
powersFormulaIdentifier,
);

if (resultName !== undefined) {
await petStore.write(resultName, formulaIdentifier);
}

return value;
};

Expand Down
Loading

0 comments on commit d90350c

Please sign in to comment.