Skip to content

Commit

Permalink
Fixing vertex dependencies issue (#247)
Browse files Browse the repository at this point in the history
Co-authored-by: droak <[email protected]>
  • Loading branch information
elielnfinic and d-roak authored Nov 16, 2024
1 parent 2c21707 commit e4a1ecf
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 12 deletions.
15 changes: 12 additions & 3 deletions packages/node/src/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export async function topologyMessagesHandler(

switch (message.type) {
case NetworkPb.Message_MessageType.UPDATE:
updateHandler(node, message.data);
updateHandler(node, message.data, message.sender);
break;
case NetworkPb.Message_MessageType.SYNC:
if (!stream) {
Expand Down Expand Up @@ -71,15 +71,19 @@ 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,
sender: string,
) {
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;
}

object.merge(
const [merged, _] = object.merge(
updateMessage.vertices.map((v) => {
return {
hash: v.hash,
Expand All @@ -92,6 +96,11 @@ function updateHandler(node: TopologyNode, data: Uint8Array) {
};
}),
);

if (!merged) {
await node.syncObject(updateMessage.objectId, sender);
}

node.objectStore.put(object.id, object);

return true;
Expand Down
8 changes: 5 additions & 3 deletions packages/object/src/hashgraph/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,20 @@ export class HashGraph {
return vertex;
}

/* Add a vertex to the hashgraph with the given operation and dependencies.
* If the vertex already exists, return the hash of the existing vertex.
* Throws an error if any of the dependencies are not present in the hashgraph.
*/
addVertex(operation: Operation, deps: Hash[], nodeId: string): Hash {
const hash = computeHash(nodeId, operation, deps);
if (this.vertices.has(hash)) {
return hash; // Vertex already exists
}

// Temporary fix: don't add the vertex if the dependencies are not present in the local HG.
if (
!deps.every((dep) => this.forwardEdges.has(dep) || this.vertices.has(dep))
) {
console.error("Invalid dependency detected.");
return "";
throw new Error("Invalid dependency detected.");
}

const vertex: Vertex = {
Expand Down
23 changes: 17 additions & 6 deletions packages/object/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,36 @@ export class TopologyObject implements ITopologyObject {
this._notify("callFn", [serializedVertex]);
}

merge(vertices: Vertex[]) {
/* Merges the vertices into the hashgraph
* Returns a tuple with a boolean indicating if there were
* missing vertices and an array with the missing vertices
*/
merge(vertices: Vertex[]): [merged: boolean, missing: string[]] {
const missing = [];
for (const vertex of vertices) {
// Check to avoid manually crafted `undefined` operations
if (!vertex.operation) {
continue;
}

this.hashGraph.addVertex(
vertex.operation,
vertex.dependencies,
vertex.nodeId,
);
try {
this.hashGraph.addVertex(
vertex.operation,
vertex.dependencies,
vertex.nodeId,
);
} catch (e) {
missing.push(vertex.hash);
}
}

const operations = this.hashGraph.linearizeOperations();
this.vertices = this.hashGraph.getAllVertices();

(this.cro as CRO).mergeCallback(operations);
this._notify("merge", this.vertices);

return [missing.length === 0, missing];
}

subscribe(callback: TopologyObjectCallback) {
Expand Down

0 comments on commit e4a1ecf

Please sign in to comment.