Skip to content

Commit

Permalink
Synchronize before merge
Browse files Browse the repository at this point in the history
  • Loading branch information
elielnfinic committed Nov 14, 2024
1 parent deda5d9 commit ac8720e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 66 deletions.
13 changes: 5 additions & 8 deletions packages/node/src/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,14 @@ export async function topologyMessagesHandler(
data: { id: string, operations: {nonce: string, fn: string, args: string[] }[] }
operations array doesn't contain the full remote operations array
*/
function updateHandler(node: TopologyNode, data: Uint8Array) {
async function updateHandler(node: TopologyNode, data: Uint8Array) {
const updateMessage = NetworkPb.Update.decode(data);
const object = node.objectStore.get(updateMessage.objectId);
if (!object) {
console.error("topology::node::updateHandler", "Object not found");
return false;
}
await node.syncObject(updateMessage.objectId, node.networkNode.peerId);
object.merge(
updateMessage.vertices.map((v) => {
return {
Expand All @@ -90,9 +91,6 @@ function updateHandler(node: TopologyNode, data: Uint8Array) {
dependencies: v.dependencies,
};
}),
async (croId: string, nodeId: string) => {
await node.syncObject(croId, nodeId);
},
);

node.objectStore.put(object.id, object);
Expand Down Expand Up @@ -150,7 +148,7 @@ function syncHandler(
data: { id: string, operations: {nonce: string, fn: string, args: string[] }[] }
operations array contain the full remote operations array
*/
function syncAcceptHandler(
async function syncAcceptHandler(
node: TopologyNode,
protocol: string,
sender: string,
Expand All @@ -176,9 +174,8 @@ function syncAcceptHandler(
});

if (vertices.length !== 0) {
object.merge(vertices, async (croId: string, nodeId: string) => {
await node.syncObject(croId, nodeId);
});
await node.syncObject(object.id, vertices[0].nodeId);
object.merge(vertices);
node.objectStore.put(object.id, object);
}

Expand Down
10 changes: 0 additions & 10 deletions packages/object/src/hashgraph/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,6 @@ export class HashGraph {
return vertex;
}

checkDependencyInHashgraph(deps: Hash[]): boolean {
if (
!deps.every((dep) => this.forwardEdges.has(dep) || this.vertices.has(dep))
) {
return false;
}

return true;
}

addVertex(operation: Operation, deps: Hash[], nodeId: string): Hash {
const hash = computeHash(nodeId, operation, deps);
if (this.vertices.has(hash)) {
Expand Down
7 changes: 0 additions & 7 deletions packages/object/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,25 +99,18 @@ export class TopologyObject implements ITopologyObject {

/*
* Merges the given vertices into the object's hashgraph.
* If `synchronizeVertices` is provided, it will be called for each vertex that cannot be merged due to a dependency issue.
* @param vertices - The vertices to merge
* @param synchronizeVertices - A callback to synchronize vertices if there is a dependency issue with the hashgraph
* @returns void
*/
async merge(
vertices: Vertex[],
synchronizeVertices: (croId: string, nodeId: string) => void,
) {
for (const vertex of vertices) {
// Check to avoid manually crafted `undefined` operations
if (!vertex.operation) {
continue;
}
if (!this.hashGraph.checkDependencyInHashgraph(vertex.dependencies)) {
if (synchronizeVertices)
await synchronizeVertices(this.id, vertex.nodeId);
}

this.hashGraph.addVertex(
vertex.operation,
vertex.dependencies,
Expand Down
82 changes: 41 additions & 41 deletions packages/object/tests/hashgraph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe("HashGraph construction tests", () => {
cro1.add(1);
cro2.add(2);

obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

expect(obj2.hashGraph.selfCheckConstraints()).toBe(true);

Expand Down Expand Up @@ -104,12 +104,12 @@ describe("HashGraph for AddWinSet tests", () => {
const cro2 = obj2.cro as AddWinsSet<number>;

cro1.add(1);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.remove(1);
cro2.add(1);
obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
obj2.merge(obj1.hashGraph.getAllVertices());

expect(cro1.contains(1)).toBe(true);
expect(obj1.hashGraph.vertices).toEqual(obj2.hashGraph.vertices);
Expand All @@ -132,12 +132,12 @@ describe("HashGraph for AddWinSet tests", () => {
const cro2 = obj2.cro as AddWinsSet<number>;

cro1.add(1);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.remove(1);
cro2.add(2);
obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
obj2.merge(obj1.hashGraph.getAllVertices());

expect(cro1.contains(1)).toBe(false);
expect(cro1.contains(2)).toBe(true);
Expand All @@ -162,14 +162,14 @@ describe("HashGraph for AddWinSet tests", () => {
const cro2 = obj2.cro as AddWinsSet<number>;

cro1.add(1);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.remove(1);
cro2.add(1);
cro1.add(10);
cro2.remove(5);
obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
obj2.merge(obj1.hashGraph.getAllVertices());

expect(cro1.contains(1)).toBe(true);
expect(cro1.contains(10)).toBe(true);
Expand All @@ -196,14 +196,14 @@ describe("HashGraph for AddWinSet tests", () => {
const cro2 = obj2.cro as AddWinsSet<number>;

cro1.add(1);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.remove(1);
cro2.remove(2);
cro1.add(2);
cro2.add(1);
obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
obj2.merge(obj1.hashGraph.getAllVertices());

expect(cro1.contains(1)).toBe(true);
expect(cro1.contains(2)).toBe(true);
Expand Down Expand Up @@ -233,27 +233,27 @@ describe("HashGraph for AddWinSet tests", () => {
const cro3 = obj3.cro as AddWinsSet<number>;

cro1.add(1);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.add(1);
cro1.remove(2);
cro2.remove(2);
cro2.add(2);

obj3.merge(obj1.hashGraph.getAllVertices(), () => {});
obj3.merge(obj1.hashGraph.getAllVertices());
cro3.add(3);
cro1.remove(1);

obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
cro1.remove(3);
cro2.remove(1);

obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj1.merge(obj3.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj3.hashGraph.getAllVertices(), () => {});
obj3.merge(obj1.hashGraph.getAllVertices(), () => {});
obj3.merge(obj2.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
obj1.merge(obj3.hashGraph.getAllVertices());
obj2.merge(obj1.hashGraph.getAllVertices());
obj2.merge(obj3.hashGraph.getAllVertices());
obj3.merge(obj1.hashGraph.getAllVertices());
obj3.merge(obj2.hashGraph.getAllVertices());

expect(cro1.contains(1)).toBe(false);
expect(cro1.contains(2)).toBe(true);
Expand Down Expand Up @@ -288,27 +288,27 @@ describe("HashGraph for AddWinSet tests", () => {
const cro3 = obj3.cro as AddWinsSet<number>;

cro1.add(1);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.add(1);
cro1.remove(2);
cro2.remove(2);

obj3.merge(obj1.hashGraph.getAllVertices(), () => {});
obj3.merge(obj1.hashGraph.getAllVertices());
cro3.add(3);
cro1.remove(1);

obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());
cro2.add(2);
cro1.remove(3);
cro2.remove(1);

obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj1.merge(obj3.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj3.hashGraph.getAllVertices(), () => {});
obj3.merge(obj1.hashGraph.getAllVertices(), () => {});
obj3.merge(obj2.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
obj1.merge(obj3.hashGraph.getAllVertices());
obj2.merge(obj1.hashGraph.getAllVertices());
obj2.merge(obj3.hashGraph.getAllVertices());
obj3.merge(obj1.hashGraph.getAllVertices());
obj3.merge(obj2.hashGraph.getAllVertices());

expect(cro1.contains(1)).toBe(false);
expect(cro1.contains(2)).toBe(true);
Expand Down Expand Up @@ -340,16 +340,16 @@ describe("HashGraph for AddWinSet tests", () => {
const cro2 = obj2.cro as AddWinsSet<number>;

cro1.add(1);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.add(2);
cro2.remove(2);
cro2.remove(2);
obj1.merge(obj2.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj1.merge(obj2.hashGraph.getAllVertices());
obj2.merge(obj1.hashGraph.getAllVertices());

cro1.remove(2);
obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

expect(cro1.contains(1)).toBe(true);
expect(cro1.contains(2)).toBe(false);
Expand Down Expand Up @@ -400,11 +400,11 @@ describe("HashGraph for PseudoRandomWinsSet tests", () => {
cro4.add(4);
cro5.add(5);

obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj3.merge(obj2.hashGraph.getAllVertices(), () => {});
obj4.merge(obj3.hashGraph.getAllVertices(), () => {});
obj5.merge(obj4.hashGraph.getAllVertices(), () => {});
obj1.merge(obj5.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());
obj3.merge(obj2.hashGraph.getAllVertices());
obj4.merge(obj3.hashGraph.getAllVertices());
obj5.merge(obj4.hashGraph.getAllVertices());
obj1.merge(obj5.hashGraph.getAllVertices());

const linearOps = obj1.hashGraph.linearizeOperations();
// Pseudo-randomly chosen operation
Expand All @@ -431,7 +431,7 @@ describe("HashGraph for undefined operations tests", () => {
// Set one of the vertice from cro1 to have undefined operation
obj1.hashGraph.getAllVertices()[1].operation = undefined;

obj2.merge(obj1.hashGraph.getAllVertices(), () => {});
obj2.merge(obj1.hashGraph.getAllVertices());

const linearOps = obj2.hashGraph.linearizeOperations();
// Should only have one, since we skipped the undefined operations
Expand Down

0 comments on commit ac8720e

Please sign in to comment.