delta.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. export class NodeCreation {
  2. readonly uuid: UUID;
  3. // Inverse dependency: Incoming and outgoing edges.
  4. edges: Array<EdgeCreation>; // append-only
  5. // Inverse dependency: Deletions of this node.
  6. deletions: Array<NodeDeletion>; // append-only
  7. constructor(uuid: UUID) {
  8. this.uuid = uuid;
  9. this.edges = [];
  10. }
  11. // Whenever a node is deleted more than once, concurrently, there's a {DELETE,DELETE}-conflict
  12. getDeleteDeleteConflicts(): Array<[NodeDeletion, NodeDeletion]> {
  13. // Basically get all pairs of 'deletions'
  14. const result = new Array(this.deletions**2)
  15. let i = 0;
  16. for (const d1 of this.deletions) {
  17. for (const d2 of this.deletions) {
  18. result[i] = [d1, d2];
  19. i++;
  20. }
  21. }
  22. return result;
  23. }
  24. // Whenever a node is deleted, and the source/target of a concurrent edge creation, there's a {DELETE,REQUIRE}-conflict.
  25. getDeleteRequireConflicts(): Array<[NodeDeletion, EdgeCreation]> {
  26. }
  27. }
  28. export class NodeDeletion {
  29. // Dependency: The node being deleted.
  30. readonly deletes: NodeCreation;
  31. // Dependency: Deletion of a node depends on deletion of its incoming and outgoing edges.
  32. readonly edgeDeletions: Array<EdgeDeletion>;
  33. constructor(deletes: NodeCreation, edgeDeletions: Array<EdgeDeletion>) {
  34. this.deletes = deletes;
  35. this.edgeDeletions = edgeDeletions;
  36. // Create inverse dependency
  37. this.deletes.deletions.append(this);
  38. }
  39. }
  40. export interface EdgeOperation {
  41. // Edge operations always form a tree (or sequence, if non-conflicting) where the path from root to leaf is as follows: create, update, update, ..., update, delete
  42. // Therefore, any 'node' in this tree traces back to a 'root', the creation.
  43. getCreation(): EdgeCreation;
  44. }
  45. export class EdgeCreation implements EdgeOperation {
  46. // Dependency: source node
  47. readonly source: NodeCreation;
  48. // Dependency: target node
  49. readonly target: NodeCreation;
  50. readonly label: string;
  51. // Inverse dependency: Next operation on the edge
  52. nextOperations: Array<EdgeUpdate | EdgeDeletion>; // append-only
  53. constructor(source: NodeCreation, label: string, target: NodeCreation) {
  54. this.source = source;
  55. this.target = target;
  56. this.label = label;
  57. this.nextOperations = [];
  58. // Create inverse dependency
  59. this.source.edges.push(this);
  60. }
  61. getCreation(): EdgeCreation {
  62. return this;
  63. }
  64. }
  65. export class EdgeUpdate implements EdgeOperation {
  66. readonly edge: EdgeCreation | EdgeUpdate; // UPD-dependency
  67. readonly newTarget: NodeCreation; // REQ-dependency
  68. // Inverse dependency: Next operation on the edge
  69. nextOperations: Array<EdgeUpdate | EdgeDeletion>; // append-only
  70. constructor(edge: EdgeCreation | EdgeUpdate, newTarget: NodeCreation) {
  71. this.edge = edge;
  72. this.newTarget = newTarget;
  73. this.nextOperations = [];
  74. // Create inverse dependency
  75. this.edge.nextOperations.push(this);
  76. }
  77. getCreation(): EdgeCreation {
  78. return this.edge.getCreation();
  79. }
  80. }
  81. export class EdgeDeletion implements EdgeOperation {
  82. readonly edge: EdgeCreation | EdgeUpdate; // UPD-dependency
  83. constructor(edge: EdgeCreation | EdgeUpdate) {
  84. this.edge = edge;
  85. // Create inverse dependency
  86. this.edge.nextOperations.push(this);
  87. }
  88. getCreation(): EdgeCreation {
  89. return this.edge.getCreation();
  90. }
  91. }