Skip to content

Commit

Permalink
feat: add helper util conductorCellsDhtSync -- alias for dhtSync (#188)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattyg authored Oct 3, 2023
1 parent 26c919f commit ae18d92
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 9 deletions.
9 changes: 9 additions & 0 deletions ts/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
AppSignalCb,
AppWebsocket,
CallZomeRequest,
CellId,
ClonedCell,
DnaBundle,
DnaProperties,
Expand Down Expand Up @@ -200,3 +201,11 @@ export interface Dna {
properties?: DnaProperties;
roleName?: string;
}

/**
* A Conductor and a CellId
*/
export interface IConductorCell {
conductor: IConductor;
cellId: CellId;
}
82 changes: 73 additions & 9 deletions ts/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "@holochain/client";
import isEqual from "lodash/isEqual.js";
import sortBy from "lodash/sortBy.js";
import { IPlayer } from "./types.js";
import { IConductorCell, IPlayer } from "./types.js";

/**
* A utility function to wait the given amount of time.
Expand All @@ -22,6 +22,12 @@ export const pause = (milliseconds: number) => {
});
};

const playersToConductorCells = (players: IPlayer[], dnaHash: DnaHash) =>
players.map((player) => ({
conductor: player.conductor,
cellId: [dnaHash, player.agentPubKey] as CellId,
}));

/**
* A utility function to compare conductors' integrated DhtOps.
*
Expand All @@ -32,28 +38,46 @@ export const pause = (milliseconds: number) => {
* @public
*/
export const areDhtsSynced = async (players: IPlayer[], dnaHash: DnaHash) => {
const conductorCells = playersToConductorCells(players, dnaHash);
return areConductorCellsDhtsSynced(conductorCells);
};

/**
* A utility function to compare conductors' integrated DhtOps.
*
* @param conductorCells - Array of ConductorCells
* @returns A promise that is resolved after conductors' Integrated DhtOps match.
*
* @public
*/
export const areConductorCellsDhtsSynced = async (
conductorCells: IConductorCell[]
) => {
if (!isConductorCellDnaHashEqual(conductorCells)) {
throw Error("Cannot compare DHT state of different DNAs");
}

// Dump all conductors' states
const conductorStates: FullStateDump[] = await Promise.all(
players.map((player) => {
const cell_id: CellId = [dnaHash, player.agentPubKey];
return player.conductor.adminWs().dumpFullState({
cell_id,
conductorCells.map((conductorCell) => {
return conductorCell.conductor.adminWs().dumpFullState({
cell_id: conductorCell.cellId,
dht_ops_cursor: undefined,
});
})
);

// Compare conductors' integrated DhtOps
const playersDhtOpsIntegrated = conductorStates.map((conductor) =>
const conductorDhtOpsIntegrated = conductorStates.map((conductor) =>
sortBy(conductor.integration_dump.integrated, [
// the only property's key of each DhtOp is the DhtOp type
(op) => Object.keys(op)[0],
// the DhtOp's signature
(op) => encodeHashToBase64(Object.values(op)[0][0]),
])
);
const status = playersDhtOpsIntegrated.every((playerOps) =>
isEqual(playerOps, playersDhtOpsIntegrated[0])
const status = conductorDhtOpsIntegrated.every((ops) =>
isEqual(ops, conductorDhtOpsIntegrated[0])
);

return status;
Expand All @@ -77,6 +101,30 @@ export const dhtSync = async (
interval = 50,
timeout?: number
) => {
const conductorCells = playersToConductorCells(players, dnaHash);
return conductorCellsDhtSync(conductorCells, interval, timeout);
};

/**
* A utility function to wait until all conductors' integrated DhtOps are
* identical for a DNA.
*
* @param conductorCells - Array of IConductorCell.
* @param interval - Interval to pause between comparisons (defaults to 50 ms).
* @param timeout - A timeout for the delay (optional).
* @returns A promise that is resolved after all agents' DHT states match.
*
* @public
*/
export const conductorCellsDhtSync = async (
conductorCells: IConductorCell[],
interval = 50,
timeout?: number
) => {
if (!isConductorCellDnaHashEqual(conductorCells)) {
throw Error("Cannot compare DHT state of different DNAs");
}

const startTime = performance.now();
let completed = false;

Expand All @@ -89,10 +137,26 @@ export const dhtSync = async (
);

// Check if Integrated DhtOps are syncronized
completed = await areDhtsSynced(players, dnaHash);
completed = await areConductorCellsDhtsSynced(conductorCells);

if (!completed) {
await pause(interval);
}
}
};

/**
* A utility function to verify if all IConductorCells in an array have CellIds with
* the same DnaHash.
*
* @param conductorCells - Array of IConductorCell.
* @returns boolean
*
* @internal
*/
const isConductorCellDnaHashEqual = (conductorCells: IConductorCell[]) => {
const dnaHashes = conductorCells.map(
(conductorCell) => conductorCell.cellId[0]
);
return dnaHashes.every((val: DnaHash) => val === dnaHashes[0]);
};

0 comments on commit ae18d92

Please sign in to comment.