|
@@ -30,8 +30,8 @@ export class NodeDeletion implements Delta {
|
|
|
// Dependency: The node being deleted.
|
|
|
readonly creation: NodeCreation;
|
|
|
|
|
|
- // Dependency: Deletion of a node depends on deletion of its outgoing edges.
|
|
|
- readonly deletedOutgoingEdges: Array<EdgeCreation>;
|
|
|
+ // Dependency: All incoming and outgoing edges of this node must be deleted also.
|
|
|
+ readonly deletedEdges: Array<EdgeCreation | EdgeUpdate>;
|
|
|
|
|
|
// Conflicts: Concurrent deletion of the same node.
|
|
|
deleteConflicts: Array<NodeDeletion> = [];
|
|
@@ -40,11 +40,11 @@ export class NodeDeletion implements Delta {
|
|
|
edgeSourceConflicts: Array<EdgeCreation> = [];
|
|
|
|
|
|
// Conflicts: Concurrent update of an edge, when the edge is also deleted.
|
|
|
- // updateConflicts: Array<EdgeUpdate> = [];
|
|
|
+ updateConflicts: Array<EdgeUpdate | NodeDeletion> = [];
|
|
|
|
|
|
- constructor(creation: NodeCreation, deletedOutgoingEdges: Array<EdgeCreation>) {
|
|
|
+ constructor(creation: NodeCreation, deletedEdges: Array<EdgeCreation | EdgeUpdate>) {
|
|
|
this.creation = creation;
|
|
|
- this.deletedOutgoingEdges = deletedOutgoingEdges;
|
|
|
+ this.deletedEdges = deletedEdges;
|
|
|
|
|
|
// Detect conflicts
|
|
|
|
|
@@ -57,20 +57,30 @@ export class NodeDeletion implements Delta {
|
|
|
|
|
|
// Concurrently created outgoing edges of this node
|
|
|
for (const outgoingEdgeCreation of this.creation.outgoingEdges) {
|
|
|
- if (!this.deletedOutgoingEdges.includes(outgoingEdgeCreation)) {
|
|
|
+ if (!this.deletedEdges.some(edge => edge.getCreation() === outgoingEdgeCreation)) {
|
|
|
// Symmetric
|
|
|
this.edgeSourceConflicts.push(outgoingEdgeCreation);
|
|
|
outgoingEdgeCreation.deleteSourceConflicts.push(this);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Concurrent edge updates
|
|
|
+ for (const deletedEdge of this.deletedEdges) {
|
|
|
+ for (const concurrentEdgeUpdate of deletedEdge.overwrittenBy) {
|
|
|
+ // Symmetric
|
|
|
+ this.updateConflicts.push(concurrentEdgeUpdate);
|
|
|
+ concurrentEdgeUpdate.updateConflicts.push(this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Create inverse dependencies
|
|
|
|
|
|
this.creation.deletions.push(this);
|
|
|
|
|
|
- // for (const deletedOutgoingEdge of this.deletedOutgoingEdges) {
|
|
|
- // deletedOutgoingEdge.overwrittenBy.push(this);
|
|
|
- // }
|
|
|
+ for (const deletedEdge of this.deletedEdges) {
|
|
|
+ // NodeDeletion acts a bit as an EdgeUpdate here
|
|
|
+ deletedEdge.overwrittenBy.push(this);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
getDependencies(): [NodeCreation] {
|
|
@@ -81,7 +91,7 @@ export class NodeDeletion implements Delta {
|
|
|
return Array<Delta>().concat(
|
|
|
this.deleteConflicts,
|
|
|
this.edgeSourceConflicts,
|
|
|
- // this.updateConflicts,
|
|
|
+ this.updateConflicts,
|
|
|
);
|
|
|
}
|
|
|
}
|
|
@@ -94,8 +104,8 @@ export class EdgeCreation implements Delta {
|
|
|
|
|
|
// Inverse dependency
|
|
|
// NodeDeletion if source of edge is deleted.
|
|
|
- // overwrittenBy: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
- overwrittenBy: Array<EdgeUpdate> = []; // append-only
|
|
|
+ overwrittenBy: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
+ // overwrittenBy: Array<EdgeUpdate> = []; // append-only
|
|
|
|
|
|
// Conflicts: Concurrent creations of the same edge.
|
|
|
createConflicts: Array<EdgeCreation> = []; // append-only
|
|
@@ -121,7 +131,7 @@ export class EdgeCreation implements Delta {
|
|
|
|
|
|
// Concurrent deletions of source node
|
|
|
for (const sourceDeletion of this.source.deletions) {
|
|
|
- if (sourceDeletion.deletedOutgoingEdges.includes(this))
|
|
|
+ if (sourceDeletion.deletedEdges.some(edge => edge.getCreation() === this))
|
|
|
throw new Error("Assertion failed - did not expect existing deletion to be aware of a new edge creation")
|
|
|
// Symmetric
|
|
|
this.deleteSourceConflicts.push(sourceDeletion);
|
|
@@ -132,6 +142,11 @@ export class EdgeCreation implements Delta {
|
|
|
this.source.outgoingEdges.push(this);
|
|
|
}
|
|
|
|
|
|
+ // Helper
|
|
|
+ getCreation(): EdgeCreation {
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
getDependencies(): [NodeCreation, NodeCreation] {
|
|
|
return [this.source, this.target];
|
|
|
}
|
|
@@ -151,12 +166,12 @@ export class EdgeUpdate implements Delta {
|
|
|
|
|
|
// Inverse dependency
|
|
|
// NodeDeletion if source of edge is deleted.
|
|
|
- // overwrittenBy: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
- overwrittenBy: Array<EdgeUpdate> = []; // append-only
|
|
|
+ overwrittenBy: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
+ // overwrittenBy: Array<EdgeUpdate> = []; // append-only
|
|
|
|
|
|
// Conflicts: Concurrent updates
|
|
|
// updateConflicts: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
- updateConflicts: Array<EdgeUpdate> = []; // append-only
|
|
|
+ updateConflicts: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
|
|
|
constructor(overwrites: EdgeCreation | EdgeUpdate, newTarget: NodeCreation) {
|
|
|
this.overwrites = overwrites;
|
|
@@ -173,6 +188,11 @@ export class EdgeUpdate implements Delta {
|
|
|
this.overwrites.overwrittenBy.push(this);
|
|
|
}
|
|
|
|
|
|
+ // Helper
|
|
|
+ getCreation(): EdgeCreation {
|
|
|
+ return this.overwrites.getCreation();
|
|
|
+ }
|
|
|
+
|
|
|
getDependencies(): Array<Delta> {
|
|
|
return [this.overwrites, this.newTarget];
|
|
|
}
|