-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path7-or-set.js
More file actions
93 lines (79 loc) · 2.05 KB
/
7-or-set.js
File metadata and controls
93 lines (79 loc) · 2.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
'use strict';
const crypto = require('node:crypto');
class ORSet {
#added;
#removed;
constructor({ added = {}, removed = {} } = {}) {
this.#added = { ...added };
this.#removed = { ...removed };
}
add(item, tag = crypto.randomUUID()) {
if (!this.#added[item]) this.#added[item] = new Set();
this.#added[item].add(tag);
return tag;
}
remove(item) {
if (!this.#added[item]) return;
if (!this.#removed[item]) this.#removed[item] = new Set();
for (const tag of this.#added[item]) {
this.#removed[item].add(tag);
}
}
merge(instance) {
const added = Object.entries(instance.added);
for (const [item, tags] of added) {
if (!this.#added[item]) this.#added[item] = new Set();
for (const tag of tags) {
this.#added[item].add(tag);
}
}
const removed = Object.entries(instance.removed);
for (const [item, tags] of removed) {
if (!this.#removed[item]) this.#removed[item] = new Set();
for (const tag of tags) {
this.#removed[item].add(tag);
}
}
}
get value() {
const result = [];
for (const item of Object.keys(this.#added)) {
const addTags = this.#added[item] || new Set();
const remTags = this.#removed[item] || new Set();
for (const tag of addTags) {
if (!remTags.has(tag)) {
result.push(item);
break;
}
}
}
return result;
}
get added() {
return this.#added;
}
get removed() {
return this.#removed;
}
}
// Usage
console.log('Replica 0');
const set0 = new ORSet();
set0.add('a');
set0.add('b');
set0.remove('a');
console.log({ id0: set0.value });
console.log('Replica 1');
const set1 = new ORSet();
set1.add('b');
set1.add('c');
set1.remove('b');
console.log({ id1: set1.value });
console.log('Sync');
set0.merge(set1);
set1.merge(set0);
console.log({ id0: { added: set0.added, removed: set0.removed } });
console.log({ id1: { added: set1.added, removed: set1.removed } });
console.log('Get value');
console.log({ id0: set0.value });
console.log({ id1: set1.value });