@metamask/ocap-kernel
Version:
OCap kernel core components
212 lines • 7.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSubclusterMethods = getSubclusterMethods;
const errors_1 = require("@endo/errors");
const kernel_errors_1 = require("@metamask/kernel-errors");
const base_ts_1 = require("./base.cjs");
/**
* Get a subcluster store object that provides functionality for managing subcluster records.
*
* @param ctx - The store context.
* @returns A subcluster store object that maps various persistent kernel data
* structures.
*/
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function getSubclusterMethods(ctx) {
const { kv } = ctx;
const { incCounter } = (0, base_ts_1.getBaseMethods)(kv);
/**
* Retrieves all subclusters from persistent storage.
*
* @returns An array of all stored subclusters.
*/
function getSubclusters() {
const subclustersJSON = ctx.subclusters.get();
return subclustersJSON ? JSON.parse(subclustersJSON) : [];
}
/**
* Saves all subclusters to persistent storage.
*
* @param subclusters - The array of subclusters to save.
*/
function saveAllSubclustersToStorage(subclusters) {
ctx.subclusters.set(JSON.stringify(subclusters));
}
/**
* Retrieves the vat to subcluster mapping from persistent storage.
*
* @returns A record mapping VatIds to SubclusterIds.
*/
function getVatToSubclusterMap() {
const mapJSON = ctx.vatToSubclusterMap.get();
return mapJSON ? JSON.parse(mapJSON) : {};
}
/**
* Saves the vat to subcluster mapping to persistent storage.
*
* @param map - The vat to subcluster map to save.
*/
function saveVatToSubclusterMapToStorage(map) {
ctx.vatToSubclusterMap.set(JSON.stringify(map));
}
/**
* Adds a new subcluster with the given configuration.
*
* @param config - The configuration for the new subcluster.
* @returns The ID of the newly created subcluster.
*/
function addSubcluster(config) {
const currentSubclusters = getSubclusters();
const newId = `s${incCounter(ctx.nextSubclusterId)}`;
const newSubcluster = {
id: newId,
config,
vats: [],
};
currentSubclusters.push(newSubcluster);
saveAllSubclustersToStorage(currentSubclusters);
return newId;
}
/**
* Retrieves a specific subcluster by its ID.
*
* @param subclusterId - The ID of the subcluster to retrieve.
* @returns The subcluster if found, otherwise undefined.
*/
function getSubcluster(subclusterId) {
const currentSubclusters = getSubclusters();
return currentSubclusters.find((sc) => sc.id === subclusterId);
}
/**
* Adds a vat to the specified subcluster.
*
* @param subclusterId - The ID of the subcluster.
* @param vatId - The ID of the vat to add.
* @throws If the subcluster is not found.
*/
function addSubclusterVat(subclusterId, vatId) {
const currentSubclusters = getSubclusters();
const subcluster = currentSubclusters.find((sc) => sc.id === subclusterId);
if (!subcluster) {
throw new kernel_errors_1.SubclusterNotFoundError(subclusterId);
}
// Update vat mapping
const currentMap = getVatToSubclusterMap();
// Check if vat is already in another subcluster
if (currentMap[vatId] && currentMap[vatId] !== subclusterId) {
throw new Error(`Cannot add vat ${vatId} to subcluster ${subclusterId} as it already belongs to subcluster ${currentMap[vatId]}.`);
}
// Add vat to subcluster if not already present
if (!subcluster.vats.includes(vatId)) {
subcluster.vats.push(vatId);
}
// Update the map and save all changes
currentMap[vatId] = subclusterId;
saveVatToSubclusterMapToStorage(currentMap);
saveAllSubclustersToStorage(currentSubclusters);
}
/**
* Retrieves all VATs associated with a specific subcluster.
*
* @param subclusterId - The ID of the subcluster.
* @returns An array of VatIds associated with the subcluster.
* @throws If the subcluster is not found.
*/
function getSubclusterVats(subclusterId) {
const subcluster = getSubcluster(subclusterId);
if (!subcluster) {
throw new kernel_errors_1.SubclusterNotFoundError(subclusterId);
}
return [...subcluster.vats];
}
/**
* Deletes a vat from a specified subcluster.
*
* @param subclusterId - The ID of the subcluster.
* @param vatId - The ID of the vat to delete.
*/
function deleteSubclusterVat(subclusterId, vatId) {
const currentSubclusters = getSubclusters();
const subcluster = currentSubclusters.find((sc) => sc.id === subclusterId);
// Remove vat from subcluster's vats array if subcluster exists
if (subcluster) {
const vatIndex = subcluster.vats.indexOf(vatId);
if (vatIndex > -1) {
subcluster.vats.splice(vatIndex, 1);
saveAllSubclustersToStorage(currentSubclusters);
}
}
// Always remove vat from the mapping if it points to this subcluster
const currentMap = getVatToSubclusterMap();
if (currentMap[vatId] === subclusterId) {
delete currentMap[vatId];
saveVatToSubclusterMapToStorage(currentMap);
}
}
/**
* Deletes a subcluster and removes its VATs from the vat-to-subcluster map.
*
* @param subclusterId - The ID of the subcluster to delete.
*/
function deleteSubcluster(subclusterId) {
const currentSubclusters = getSubclusters();
const subclusterToDelete = currentSubclusters.find((sc) => sc.id === subclusterId);
if (!subclusterToDelete) {
return;
}
// Remove subcluster from the list
const updatedSubclusters = currentSubclusters.filter((sc) => sc.id !== subclusterId);
saveAllSubclustersToStorage(updatedSubclusters);
// Remove all vats from the mapping
const currentMap = getVatToSubclusterMap();
const vatsToRemove = subclusterToDelete.vats.filter((vatId) => currentMap[vatId] === subclusterId);
if (vatsToRemove.length > 0) {
for (const vatId of vatsToRemove) {
delete currentMap[vatId];
}
saveVatToSubclusterMapToStorage(currentMap);
}
}
/**
* Retrieves the subcluster ID for a given vat ID.
*
* @param vatId - The ID of the vat.
* @returns The ID of the subcluster the vat belongs to, or undefined if not found.
*/
function getVatSubcluster(vatId) {
const currentMap = getVatToSubclusterMap();
return currentMap[vatId] ?? (0, errors_1.Fail) `Vat ${vatId} has no subcluster`;
}
/**
* Clears empty subclusters.
*/
function clearEmptySubclusters() {
const currentSubclusters = getSubclusters();
const nonEmptySubclusters = currentSubclusters.filter((sc) => sc.vats.length > 0);
if (nonEmptySubclusters.length !== currentSubclusters.length) {
saveAllSubclustersToStorage(nonEmptySubclusters);
}
}
/**
* Removes a vat from its subcluster.
*
* @param vatId - The ID of the vat to remove.
*/
function removeVatFromSubcluster(vatId) {
const subclusterId = getVatSubcluster(vatId);
deleteSubclusterVat(subclusterId, vatId);
}
return {
addSubcluster,
getSubcluster,
getSubclusters,
deleteSubcluster,
addSubclusterVat,
getSubclusterVats,
deleteSubclusterVat,
getVatSubcluster,
clearEmptySubclusters,
removeVatFromSubcluster,
};
}
//# sourceMappingURL=subclusters.cjs.map