|
@@ -0,0 +1,478 @@
|
|
|
|
+import {UUID} from "./types";
|
|
|
|
+
|
|
|
|
+import {
|
|
|
|
+ Delta,
|
|
|
|
+} from "./delta";
|
|
|
|
+
|
|
|
|
+export class NodeCreation implements Delta {
|
|
|
|
+ readonly id: UUID;
|
|
|
|
+
|
|
|
|
+ // Inverse dependency: Deletions of this node.
|
|
|
|
+ deletions: Array<NodeDeletion> = []; // append-only
|
|
|
|
+
|
|
|
|
+ // Inverse dependency: Creation outgoing edges.
|
|
|
|
+ outgoingEdges: Array<EdgeCreation> = []; // append-only
|
|
|
|
+
|
|
|
|
+ constructor(id: UUID) {
|
|
|
|
+ this.id = id;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getDependencies(): [] {
|
|
|
|
+ return [];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getConflicts(): [] {
|
|
|
|
+ return [];
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export class NodeDeletion implements Delta {
|
|
|
|
+ // Dependency: The node being deleted.
|
|
|
|
+ readonly creation: NodeCreation;
|
|
|
|
+
|
|
|
|
+ // Dependency: Deletion of a node depends on deletion of its incoming and outgoing edges.
|
|
|
|
+ // readonly deletedEdges: Array<EdgeUpdate2>;
|
|
|
|
+
|
|
|
|
+ // Conflicts: Concurrent deletion of the same node.
|
|
|
|
+ deleteConflicts: Array<NodeDeletion> = [];
|
|
|
|
+
|
|
|
|
+ // Conflicts: Concurrent creation of an edge with as source the deleted node.
|
|
|
|
+ // requireConflicts: Array<EdgeUpdate2>;
|
|
|
|
+
|
|
|
|
+ constructor(creation: NodeCreation/*, deletedEdges: Array<EdgeDeletion>*/) {
|
|
|
|
+ this.creation = creation;
|
|
|
|
+ // this.deletedEdges = deletedEdges;
|
|
|
|
+
|
|
|
|
+ // Detect conflicts
|
|
|
|
+ for (const concurrentDeletion of this.creation.deletions) {
|
|
|
|
+ // Symmetric:
|
|
|
|
+ this.deleteConflicts.push(concurrentDeletion);
|
|
|
|
+ concurrentDeletion.deleteConflicts.push(this);
|
|
|
|
+ }
|
|
|
|
+ // this.requireConflicts = [];
|
|
|
|
+ // for (const edgeCreation of this.creation.edges) {
|
|
|
|
+ // // Incoming or outgoing edge
|
|
|
|
+ // if (! this.deletedEdges.some(del => del.getCreation() === edgeCreation)) {
|
|
|
|
+ // // Symmetric:
|
|
|
|
+ // this.requireConflicts.push(edgeCreation);
|
|
|
|
+ // edgeCreation.deleteConflicts.push(this);
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // Create inverse dependency
|
|
|
|
+ this.creation.deletions.push(this);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getDependencies(): [NodeCreation] {
|
|
|
|
+ return [this.creation];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getConflicts(): Array<Delta> {
|
|
|
|
+ // return [].concat(
|
|
|
|
+ // this.deleteConflicts,
|
|
|
|
+ // this.requireConflicts,
|
|
|
|
+ // );
|
|
|
|
+ return this.deleteConflicts;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export class EdgeCreation implements Delta {
|
|
|
|
+ // Dependencies
|
|
|
|
+ readonly source: NodeCreation;
|
|
|
|
+ readonly label: string;
|
|
|
|
+ readonly target: NodeCreation;
|
|
|
|
+
|
|
|
|
+ // Inverse dependency
|
|
|
|
+ // NodeDeletion if source of edge is deleted.
|
|
|
|
+ overwrittenBy: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
|
+
|
|
|
|
+ // Conflicts: Concurrent creations of the same edge.
|
|
|
|
+ createConflicts: Array<EdgeCreation> = []; // append-only
|
|
|
|
+
|
|
|
|
+ constructor(source: NodeCreation, label: string, target: NodeCreation) {
|
|
|
|
+ this.source = source;
|
|
|
|
+ this.label = label;
|
|
|
|
+ this.target = target;
|
|
|
|
+
|
|
|
|
+ // Detect conflicts
|
|
|
|
+ for (const outgoingEdge of this.source.outgoingEdges) {
|
|
|
|
+ if (outgoingEdge.label === this.label) {
|
|
|
|
+ // Symmetric:
|
|
|
|
+ this.createConflicts.push(outgoingEdge);
|
|
|
|
+ outgoingEdge.createConflicts.push(this);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Create inverse dependency
|
|
|
|
+ this.source.outgoingEdges.push(this);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getDependencies(): [NodeCreation, NodeCreation] {
|
|
|
|
+ return [this.source, this.target];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getConflicts(): Array<EdgeCreation> {
|
|
|
|
+ return this.createConflicts;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export class EdgeUpdate implements Delta {
|
|
|
|
+ // Dependencies
|
|
|
|
+ readonly overwrites: EdgeCreation | EdgeUpdate;
|
|
|
|
+ readonly newTarget: NodeCreation;
|
|
|
|
+
|
|
|
|
+ // Inverse dependency
|
|
|
|
+ // NodeDeletion if source of edge is deleted.
|
|
|
|
+ overwrittenBy: Array<EdgeUpdate | NodeDeletion> = []; // append-only
|
|
|
|
+
|
|
|
|
+ // Conflicts: Concurrent updates
|
|
|
|
+ updateConflicts: Array<EdgeUpdate> = []; // append-only
|
|
|
|
+
|
|
|
|
+ constructor(overwrites: EdgeCreation | EdgeUpdate, newTarget: NodeCreation) {
|
|
|
|
+ this.overwrites = overwrites;
|
|
|
|
+ this.newTarget = newTarget;
|
|
|
|
+
|
|
|
|
+ // Detect conflicts
|
|
|
|
+ for (const concurrentUpdate of this.overwrites.overwrittenBy) {
|
|
|
|
+ // Symmetric
|
|
|
|
+ this.updateConflicts.push(concurrentUpdate);
|
|
|
|
+ concurrentUpdate.updateConflicts.push(this);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Create inverse dependency
|
|
|
|
+ this.overwrites.overwrittenBy.push(this);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getDependencies(): Array<Delta> {
|
|
|
|
+ return [this.overwrites, this.newTarget];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getConflicts(): Array<EdgeUpdate> {
|
|
|
|
+ return this.updateConflicts;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// export class EdgeUpdate {
|
|
|
|
+// // Dependency: The (new) target node
|
|
|
|
+// readonly newTarget: NodeCreation;
|
|
|
|
+
|
|
|
|
+// // Dependency: The previous update of the same edge
|
|
|
|
+// readonly overwrites: EdgeUpdate | null;
|
|
|
|
+
|
|
|
|
+// constructor(newTarget: NodeCreation, overwrites: EdgeUpdate | null) {
|
|
|
|
+// this.newTarget = newTarget;
|
|
|
|
+// this.overwrites = overwrites;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// abstract class EdgeCreationOrUpdate {
|
|
|
|
+// // Dependency: (new) target node
|
|
|
|
+
|
|
|
|
+// // Inverse dependency: Next operation on the edge
|
|
|
|
+// nextOperations: Array<EdgeUpdate | EdgeDeletion>; // append-only
|
|
|
|
+
|
|
|
|
+// constructor(target: NodeCreation) {
|
|
|
|
+// this.target = target;
|
|
|
|
+
|
|
|
|
+// this.nextOperations = [];
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// abstract getCreation(): EdgeCreation;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// export class EdgeCreation implements Delta {
|
|
|
|
+// // Dependencies
|
|
|
|
+// readonly source: NodeCreation;
|
|
|
|
+// readonly label: string;
|
|
|
|
+
|
|
|
|
+// // Conflicts: Concurrent creation of the same edge.
|
|
|
|
+// createConflicts: Array<EdgeCreation>;
|
|
|
|
+
|
|
|
|
+// // Conflicts: Concurrent deletion of source or target of this edge.
|
|
|
|
+// sourceDeleteConflicts: Array<NodeDeletion>;
|
|
|
|
+
|
|
|
|
+// // Inverse dependency
|
|
|
|
+// overwrittenBy: Array<EdgeUpdate2>;
|
|
|
|
+
|
|
|
|
+// constructor(source: NodeCreation, label: string) {
|
|
|
|
+// super(target);
|
|
|
|
+
|
|
|
|
+// this.source = source;
|
|
|
|
+// this.label = label;
|
|
|
|
+
|
|
|
|
+// // Detect conflicts
|
|
|
|
+// for (const concurrentCreation of this.source.edges) {
|
|
|
|
+// if (concurrentCreation.label === this.label) {
|
|
|
|
+// this.createConflicts.push(concurrentCreation);
|
|
|
|
+// concurrentCreation.createConflicts.push(this);
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// const detectDeleteConflicts = nodeCreation => {
|
|
|
|
+// for (const concurrentDeletion of nodeCreation.deletions) {
|
|
|
|
+// if (!concurrentDeletion.some(del => del.getCreation() === this)) {
|
|
|
|
+// this.sourceDeleteConflicts.push(concurrentDeletion);
|
|
|
|
+// concurrentDeletion.requireConflicts.push(this);
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// detectDeleteConflicts(this.source);
|
|
|
|
+
|
|
|
|
+// // Create inverse dependency
|
|
|
|
+// this.source.sourceEdges.push(this);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getCreation(): EdgeCreation {
|
|
|
|
+// return this;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getDependencies(): [NodeCreation, NodeCreation] {
|
|
|
|
+// return [this.source, this.target];
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getConflicts(): Array<Delta> {
|
|
|
|
+// return [].concat(
|
|
|
|
+// this.createConflicts,
|
|
|
|
+// this.sourceDeleteConflicts,
|
|
|
|
+// );
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// export class EdgeUpdate2 implements Delta {
|
|
|
|
+// // dependencies
|
|
|
|
+// readonly overwrites: EdgeCreation | EdgeUpdate2;
|
|
|
|
+// readonly newTarget: NodeCreation | null; // null if edge is deleted.
|
|
|
|
+
|
|
|
|
+// // inverse dependency: edge target is updated, or target
|
|
|
|
+// overwrittenBy: Array<EdgeUpdate2 | NodeDeletion>;
|
|
|
|
+
|
|
|
|
+// // Conflicts: concurrent updates of the same edge
|
|
|
|
+// updateConflicts: Array<EdgeUpdate2>;
|
|
|
|
+
|
|
|
|
+// // Conflicts: concurrent delete of target
|
|
|
|
+// targetDeleteConflicts: Array<NodeDeletion>;
|
|
|
|
+
|
|
|
|
+// constructor(overwrites: EdgeCreation | EdgeUpdate2, newTarget: NodeCreation | null) {
|
|
|
|
+// this.overwrites = overwrites;
|
|
|
|
+// this.newTarget = newTarget;
|
|
|
|
+
|
|
|
|
+// this.overwrittenBy = [];
|
|
|
|
+
|
|
|
|
+// for (const concurrentUpdate of this.overwrites.overwrittenBy) {
|
|
|
|
+// // Symmetric:
|
|
|
|
+// this.updateConflicts.push(concurrentUpdate);
|
|
|
|
+// concurrentUpdate.updateConflicts.push(this);
|
|
|
|
+// }
|
|
|
|
+// if (newTarget !== null) {
|
|
|
|
+// for (const concurrentTargetDeletion of this.newTarget.deletions) {
|
|
|
|
+// if (concurrentTargetDeletion.)
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // create inverse dependency
|
|
|
|
+// this.overwrites.overwrittenBy.push(this);
|
|
|
|
+
|
|
|
|
+// // create inverse dependency
|
|
|
|
+// this.newTarget.targetEdges.push(this);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getCreation(): EdgeCreation {
|
|
|
|
+// let overwrites = this.overwrites;
|
|
|
|
+// while (true) {
|
|
|
|
+// if (overwrites instanceof EdgeCreation) {
|
|
|
|
+// return this.overwrites;
|
|
|
|
+// }
|
|
|
|
+// overwrites = overwrites.overwrites;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getDependencies(): Array<Delta> {
|
|
|
|
+// this.newTarget !== null ? [this.overwrites, this.newTarget] : [this.overwrites];
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getConflicts(): Array<Delta> {
|
|
|
|
+// return this.updateConflicts;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// export class EdgeUpdate extends EdgeCreationOrUpdate implements EdgeOperation {
|
|
|
|
+// readonly edge: EdgeCreation | EdgeUpdate; // UPD-dependency
|
|
|
|
+
|
|
|
|
+// constructor(edge: EdgeCreation | EdgeUpdate, newTarget: NodeCreation) {
|
|
|
|
+// super(newTarget);
|
|
|
|
+
|
|
|
|
+// this.edge = edge;
|
|
|
|
+
|
|
|
|
+// // Create inverse dependency
|
|
|
|
+// this.edge.nextOperations.push(this);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getCreation(): EdgeCreation {
|
|
|
|
+// return this.edge.getCreation();
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getDependencies(): [EdgeCreation | EdgeUpdate] {
|
|
|
|
+// return [this.edge];
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// export class EdgeDeletion implements EdgeOperation {
|
|
|
|
+// readonly edge: EdgeCreation | EdgeUpdate; // UPD-dependency
|
|
|
|
+
|
|
|
|
+// constructor(edge: EdgeCreation | EdgeUpdate) {
|
|
|
|
+// this.edge = edge;
|
|
|
|
+
|
|
|
|
+// // Create inverse dependency
|
|
|
|
+// this.edge.nextOperations.push(this);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getCreation(): EdgeCreation {
|
|
|
|
+// return this.edge.getCreation();
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// getDependencies(): [EdgeCreation | EdgeUpdate] {
|
|
|
|
+// return [this.edge];
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // CONFLICT TYPES //
|
|
|
|
+
|
|
|
|
+// // Two concurrent deletes of the same node
|
|
|
|
+// export class DeleteDeleteConflict implements Conflict {
|
|
|
|
+// readonly del0: NodeDeletion;
|
|
|
|
+// readonly del1: NodeDeletion;
|
|
|
|
+
|
|
|
|
+// constructor(del0: NodeDeletion, del1: NodeDeletion) {
|
|
|
|
+// this.del0 = del0;
|
|
|
|
+// this.del1 = del1;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// first(): MicroOp {
|
|
|
|
+// return this.del0;
|
|
|
|
+// }
|
|
|
|
+// second(): MicroOp {
|
|
|
|
+// return this.del1;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // When a node is deleted, and concurrently an edge from/to that node is created.
|
|
|
|
+// export class DeleteRequireConflict implements Conflict {
|
|
|
|
+// readonly del: NodeDeletion;
|
|
|
|
+// readonly edge: EdgeCreation;
|
|
|
|
+
|
|
|
|
+// constructor(del: NodeDeletion, edge: EdgeCreation) {
|
|
|
|
+// this.del = del;
|
|
|
|
+// this.edge = edge;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// first(): MicroOp {
|
|
|
|
+// return this.del;
|
|
|
|
+// }
|
|
|
|
+// second(): MicroOp {
|
|
|
|
+// return this.edge;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // Two edges with the same source and label concurrently created
|
|
|
|
+// export class EdgeCreateConflict implements Conflict {
|
|
|
|
+// readonly edge0: EdgeCreation;
|
|
|
|
+// readonly edge1: EdgeCreation;
|
|
|
|
+
|
|
|
|
+// constructor(edge0: EdgeCreation, edge1: EdgeCreation) {
|
|
|
|
+// this.edge0 = edge0;
|
|
|
|
+// this.edge1 = edge1;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// first(): MicroOp {
|
|
|
|
+// return this.edge0;
|
|
|
|
+// }
|
|
|
|
+// second(): MicroOp {
|
|
|
|
+// return this.edge1;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // An edge is concurrently updated or deleted two times.
|
|
|
|
+// export class EdgeUpdateConflict implements Conflict {
|
|
|
|
+// readonly upd0: EdgeUpdateOrDeletion;
|
|
|
|
+// readonly upd1: EdgeUpdateOrDeletion;
|
|
|
|
+
|
|
|
|
+// constructor(upd0: EdgeUpdateOrDeletion, upd1: EdgeUpdateOrDeletion) {
|
|
|
|
+// this.upd0 = upd0;
|
|
|
|
+// this.upd1 = upd1;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// first(): MicroOp {
|
|
|
|
+// return upd0;
|
|
|
|
+// }
|
|
|
|
+// second(): MicroOp {
|
|
|
|
+// return upd1;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// export class MicroOpGraph {
|
|
|
|
+// conflictRegistry: ConflictRegistry
|
|
|
|
+
|
|
|
|
+// constructor() {
|
|
|
|
+// this.conflictRegistry = new ConflictRegistry();
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// newNodeCreation(id: UUID): NodeCreation {
|
|
|
|
+// return new NodeCreation(id);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // Besides the operation object, also returns newly created conflicts
|
|
|
|
+// newNodeDeletion(nodeCreation: NodeCreation, edgeDeletions: Array<EdgeDeletion>): [NodeDeletion, DeleteDeleteConflict[], DeleteRequireConflict[]] {
|
|
|
|
+// const nodeDeletion = new NodeDeletion(nodeCreation, edgeDeletions);
|
|
|
|
+// const deleteDeleteConflicts = nodeCreation.deletions
|
|
|
|
+// .filter(nodeDeletion2 => nodeDeletion2 !== nodeDeletion)
|
|
|
|
+// .map(nodeDeletion2 => new DeleteDeleteConflict(nodeDeletion, nodeDeletion2));
|
|
|
|
+// const deleteRequireConflicts = nodeCreation.edges
|
|
|
|
+// .filter(edge => !edgeDeletions.some(edgeDeletion => edge === edgeDeletion.getCreation()))
|
|
|
|
+// .map(edge => new DeleteRequireConflict(nodeDeletion, edge));
|
|
|
|
+
|
|
|
|
+// deleteDeleteConflicts.forEach(c => this.conflictRegistry.registerConflict(c));
|
|
|
|
+// deleteRequireConflicts.forEach(c => this.conflictRegistry.registerConflict(c));
|
|
|
|
+
|
|
|
|
+// return [nodeDeletion, deleteDeleteConflicts, deleteRequireConflicts];
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // Besides the operation object, also returns newly created conflicts
|
|
|
|
+// newEdgeCreation(source: NodeCreation, label: string, target: NodeCreation): [EdgeCreation, EdgeCreateConflict[], DeleteRequireConflict[]] {
|
|
|
|
+// const edgeCreation = new EdgeCreation(source, label, target);
|
|
|
|
+// const edgeCreationConflicts = source.edges
|
|
|
|
+// .filter(edgeCreation2 => edgeCreation2 !== edgeCreation && edgeCreation2.label === label)
|
|
|
|
+// .map(edgeCreation2 => new EdgeCreateConflict(edgeCreation, edgeCreation2));
|
|
|
|
+// function getDeleteRequireConflicts(nodeCreation) {
|
|
|
|
+// return nodeCreation.deletions
|
|
|
|
+// .filter(nodeDeletion => !nodeDeletion.edgeDeletions.some(edgeDeletion => edgeCreation === edgeDeletion.getCreation()))
|
|
|
|
+// .map(nodeDeletion => new DeleteRequireConflict(nodeDeletion, edgeCreation))
|
|
|
|
+// }
|
|
|
|
+// const deleteRequireConflicts = getDeleteRequireConflicts(source).concat(getDeleteRequireConflicts(target));
|
|
|
|
+
|
|
|
|
+// edgeCreationConflicts.forEach(c => this.conflictRegistry.registerConflict(c));
|
|
|
|
+// deleteRequireConflicts.forEach(c => this.conflictRegistry.registerConflict(c));
|
|
|
|
+
|
|
|
|
+// return [edgeCreation, edgeCreationConflicts, deleteRequireConflicts];
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // newEdgeUpdate(edge: EdgeCreationOrUpdate):
|
|
|
|
+
|
|
|
|
+// // Besides the operation object, also returns newly created conflicts
|
|
|
|
+// newEdgeDeletion(edge: EdgeCreationOrUpdate): [EdgeDeletion, EdgeUpdateConflict[]] {
|
|
|
|
+// const edgeDeletion = new EdgeDeletion(edge);
|
|
|
|
+// const edgeUpdateConflicts = edge.nextOperations
|
|
|
|
+// .filter(op => op !== edgeDeletion)
|
|
|
|
+// .map(op => new EdgeUpdateConflict(edgeDeletion, op));
|
|
|
|
+
|
|
|
|
+// edgeUpdateConflicts.forEach(c => this.conflictRegistry.registerConflict(c));
|
|
|
|
+
|
|
|
|
+// return [edgeDeletion, edgeUpdateConflicts];
|
|
|
|
+// }
|
|
|
|
+// }
|