braid-text 0.2.22 → 0.2.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +159 -59
- package/package.json +1 -1
- package/test/test.js +112 -34
package/index.js
CHANGED
|
@@ -334,7 +334,8 @@ braid_text.put = async (key, options) => {
|
|
|
334
334
|
// make sure we have all these parents
|
|
335
335
|
for (let p of options_parents) {
|
|
336
336
|
let P = decode_version(p)
|
|
337
|
-
if (
|
|
337
|
+
if (!resource.actor_seqs[P[0]]?.has(P[1]))
|
|
338
|
+
throw new Error(`${MISSING_PARENT_VERSION}: ${p}`)
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
341
|
|
|
@@ -378,7 +379,7 @@ braid_text.put = async (key, options) => {
|
|
|
378
379
|
max_pos))
|
|
379
380
|
|
|
380
381
|
// validate version: make sure we haven't seen it already
|
|
381
|
-
if (
|
|
382
|
+
if (resource.actor_seqs[v[0]]?.has(v[1])) {
|
|
382
383
|
|
|
383
384
|
if (!options.validate_already_seen_versions) return
|
|
384
385
|
|
|
@@ -439,7 +440,8 @@ braid_text.put = async (key, options) => {
|
|
|
439
440
|
// we already have this version, so nothing left to do
|
|
440
441
|
return
|
|
441
442
|
}
|
|
442
|
-
resource.actor_seqs[v[0]]
|
|
443
|
+
if (!resource.actor_seqs[v[0]]) resource.actor_seqs[v[0]] = new RangeSet()
|
|
444
|
+
resource.actor_seqs[v[0]].add_range(v[1] + 1 - change_count, v[1])
|
|
443
445
|
|
|
444
446
|
// reduce the version sequence by the number of char-edits
|
|
445
447
|
v = `${v[0]}-${v[1] + 1 - change_count}`
|
|
@@ -580,28 +582,6 @@ braid_text.put = async (key, options) => {
|
|
|
580
582
|
await resource.db_delta(resource.doc.getPatchSince(v_before))
|
|
581
583
|
}
|
|
582
584
|
|
|
583
|
-
braid_text.revert = async (key, version) => {
|
|
584
|
-
var resource = (typeof key == 'string') ? await get_resource(key) : key
|
|
585
|
-
|
|
586
|
-
// revert dt
|
|
587
|
-
var old_doc = resource.doc
|
|
588
|
-
resource.doc = dt_get(resource.doc, null, null, version)
|
|
589
|
-
old_doc.free()
|
|
590
|
-
|
|
591
|
-
for (let v of version) {
|
|
592
|
-
var [actor, seq] = decode_version(v)
|
|
593
|
-
if ((resource.actor_seqs[actor] ?? -1) > seq - 1) {
|
|
594
|
-
if (seq > 0) resource.actor_seqs[actor] = seq - 1
|
|
595
|
-
else delete resource.actor_seqs[actor]
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
resource.val = resource.doc.get()
|
|
600
|
-
|
|
601
|
-
// save it
|
|
602
|
-
await resource.db_delta()
|
|
603
|
-
}
|
|
604
|
-
|
|
605
585
|
braid_text.list = async () => {
|
|
606
586
|
try {
|
|
607
587
|
if (braid_text.db_folder) {
|
|
@@ -645,7 +625,8 @@ async function get_resource(key) {
|
|
|
645
625
|
let max_version = resource.doc.getLocalVersion().reduce((a, b) => Math.max(a, b), -1)
|
|
646
626
|
for (let i = 0; i <= max_version; i++) {
|
|
647
627
|
let v = resource.doc.localToRemoteVersion([i])[0]
|
|
648
|
-
resource.actor_seqs[v[0]]
|
|
628
|
+
if (!resource.actor_seqs[v[0]]) resource.actor_seqs[v[0]] = new RangeSet()
|
|
629
|
+
resource.actor_seqs[v[0]].add_range(v[1], v[1])
|
|
649
630
|
}
|
|
650
631
|
|
|
651
632
|
resource.val = resource.doc.get()
|
|
@@ -819,20 +800,8 @@ function dt_len(doc, version) {
|
|
|
819
800
|
function dt_get_string(doc, version) {
|
|
820
801
|
var bytes = doc.toBytes()
|
|
821
802
|
var oplog = OpLog.fromBytes(bytes)
|
|
822
|
-
var [_agents, versions, _parentss] = dt_parse([...bytes])
|
|
823
|
-
|
|
824
|
-
var frontier = new Set(version)
|
|
825
803
|
|
|
826
|
-
var local_version =
|
|
827
|
-
for (var i = 0; i < versions.length; i++) {
|
|
828
|
-
var v = versions[i].join("-")
|
|
829
|
-
if (frontier.has(v)) {
|
|
830
|
-
local_version.push(i)
|
|
831
|
-
frontier.delete(v)
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
if (frontier.size) throw new Error(`version not found: ${version}`)
|
|
804
|
+
var local_version = dt_get_local_version(bytes, version)
|
|
836
805
|
|
|
837
806
|
var b = new Branch()
|
|
838
807
|
b.merge(oplog, new Uint32Array(local_version))
|
|
@@ -1027,25 +996,25 @@ function dt_parse(byte_array) {
|
|
|
1027
996
|
|
|
1028
997
|
while (byte_array.length) {
|
|
1029
998
|
let id = byte_array.shift()
|
|
1030
|
-
let len =
|
|
999
|
+
let len = dt_read_varint(byte_array)
|
|
1031
1000
|
if (id == 1) {
|
|
1032
1001
|
} else if (id == 3) {
|
|
1033
1002
|
let goal = byte_array.length - len
|
|
1034
1003
|
while (byte_array.length > goal) {
|
|
1035
|
-
agents.push(
|
|
1004
|
+
agents.push(dt_read_string(byte_array))
|
|
1036
1005
|
}
|
|
1037
1006
|
} else if (id == 20) {
|
|
1038
1007
|
} else if (id == 21) {
|
|
1039
1008
|
let seqs = {}
|
|
1040
1009
|
let goal = byte_array.length - len
|
|
1041
1010
|
while (byte_array.length > goal) {
|
|
1042
|
-
let part0 =
|
|
1011
|
+
let part0 = dt_read_varint(byte_array)
|
|
1043
1012
|
let has_jump = part0 & 1
|
|
1044
1013
|
let agent_i = (part0 >> 1) - 1
|
|
1045
|
-
let run_length =
|
|
1014
|
+
let run_length = dt_read_varint(byte_array)
|
|
1046
1015
|
let jump = 0
|
|
1047
1016
|
if (has_jump) {
|
|
1048
|
-
let part2 =
|
|
1017
|
+
let part2 = dt_read_varint(byte_array)
|
|
1049
1018
|
jump = part2 >> 1
|
|
1050
1019
|
if (part2 & 1) jump *= -1
|
|
1051
1020
|
}
|
|
@@ -1060,12 +1029,12 @@ function dt_parse(byte_array) {
|
|
|
1060
1029
|
let count = 0
|
|
1061
1030
|
let goal = byte_array.length - len
|
|
1062
1031
|
while (byte_array.length > goal) {
|
|
1063
|
-
let run_len =
|
|
1032
|
+
let run_len = dt_read_varint(byte_array)
|
|
1064
1033
|
|
|
1065
1034
|
let parents = []
|
|
1066
1035
|
let has_more = 1
|
|
1067
1036
|
while (has_more) {
|
|
1068
|
-
let x =
|
|
1037
|
+
let x = dt_read_varint(byte_array)
|
|
1069
1038
|
let is_foreign = 0x1 & x
|
|
1070
1039
|
has_more = 0x2 & x
|
|
1071
1040
|
let num = x >> 2
|
|
@@ -1075,7 +1044,7 @@ function dt_parse(byte_array) {
|
|
|
1075
1044
|
} else if (!is_foreign) {
|
|
1076
1045
|
parents.push(versions[count - num])
|
|
1077
1046
|
} else {
|
|
1078
|
-
parents.push([agents[num - 1],
|
|
1047
|
+
parents.push([agents[num - 1], dt_read_varint(byte_array)])
|
|
1079
1048
|
}
|
|
1080
1049
|
}
|
|
1081
1050
|
parentss.push(parents)
|
|
@@ -1091,24 +1060,107 @@ function dt_parse(byte_array) {
|
|
|
1091
1060
|
}
|
|
1092
1061
|
}
|
|
1093
1062
|
|
|
1094
|
-
|
|
1095
|
-
|
|
1063
|
+
return [agents, versions, parentss]
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
function dt_get_local_version(bytes, version) {
|
|
1067
|
+
var looking_for = new Map()
|
|
1068
|
+
for (var event of version) {
|
|
1069
|
+
var [agent, seq] = decode_version(event)
|
|
1070
|
+
if (!looking_for.has(agent)) looking_for.set(agent, [])
|
|
1071
|
+
looking_for.get(agent).push(seq)
|
|
1096
1072
|
}
|
|
1073
|
+
for (var seqs of looking_for.values())
|
|
1074
|
+
seqs.sort((a, b) => a - b)
|
|
1097
1075
|
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1076
|
+
var byte_array = [...bytes]
|
|
1077
|
+
var local_version = []
|
|
1078
|
+
var local_version_base = 0
|
|
1079
|
+
|
|
1080
|
+
if (new TextDecoder().decode(new Uint8Array(byte_array.splice(0, 8))) !== "DMNDTYPS") throw new Error("dt parse error, expected DMNDTYPS")
|
|
1081
|
+
|
|
1082
|
+
if (byte_array.shift() != 0) throw new Error("dt parse error, expected version 0")
|
|
1083
|
+
|
|
1084
|
+
let agents = []
|
|
1085
|
+
|
|
1086
|
+
while (byte_array.length && looking_for.size) {
|
|
1087
|
+
let id = byte_array.shift()
|
|
1088
|
+
let len = dt_read_varint(byte_array)
|
|
1089
|
+
if (id == 1) {
|
|
1090
|
+
} else if (id == 3) {
|
|
1091
|
+
let goal = byte_array.length - len
|
|
1092
|
+
while (byte_array.length > goal) {
|
|
1093
|
+
agents.push(dt_read_string(byte_array))
|
|
1094
|
+
}
|
|
1095
|
+
} else if (id == 20) {
|
|
1096
|
+
} else if (id == 21) {
|
|
1097
|
+
let seqs = {}
|
|
1098
|
+
let goal = byte_array.length - len
|
|
1099
|
+
while (byte_array.length > goal && looking_for.size) {
|
|
1100
|
+
let part0 = dt_read_varint(byte_array)
|
|
1101
|
+
let has_jump = part0 & 1
|
|
1102
|
+
let agent_i = (part0 >> 1) - 1
|
|
1103
|
+
let run_length = dt_read_varint(byte_array)
|
|
1104
|
+
let jump = 0
|
|
1105
|
+
if (has_jump) {
|
|
1106
|
+
let part2 = dt_read_varint(byte_array)
|
|
1107
|
+
jump = part2 >> 1
|
|
1108
|
+
if (part2 & 1) jump *= -1
|
|
1109
|
+
}
|
|
1110
|
+
let base = (seqs[agent_i] || 0) + jump
|
|
1111
|
+
|
|
1112
|
+
var agent = agents[agent_i]
|
|
1113
|
+
looking_for_seqs = looking_for.get(agent)
|
|
1114
|
+
if (looking_for_seqs) {
|
|
1115
|
+
for (var seq of splice_out_range(
|
|
1116
|
+
looking_for_seqs, base, base + run_length - 1))
|
|
1117
|
+
local_version.push(local_version_base + (seq - base))
|
|
1118
|
+
if (!looking_for_seqs.length) looking_for.delete(agent)
|
|
1119
|
+
}
|
|
1120
|
+
local_version_base += run_length
|
|
1121
|
+
|
|
1122
|
+
seqs[agent_i] = base + run_length
|
|
1123
|
+
}
|
|
1124
|
+
} else {
|
|
1125
|
+
byte_array.splice(0, len)
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
if (looking_for.size) throw new Error(`version not found: ${version}`)
|
|
1130
|
+
return local_version
|
|
1103
1131
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1132
|
+
function splice_out_range(a, s, e) {
|
|
1133
|
+
if (!a?.length) return [];
|
|
1134
|
+
let l = 0, r = a.length;
|
|
1135
|
+
while (l < r) {
|
|
1136
|
+
const m = Math.floor((l + r) / 2);
|
|
1137
|
+
if (a[m] < s) l = m + 1; else r = m;
|
|
1108
1138
|
}
|
|
1139
|
+
const i = l;
|
|
1140
|
+
l = i; r = a.length;
|
|
1141
|
+
while (l < r) {
|
|
1142
|
+
const m = Math.floor((l + r) / 2);
|
|
1143
|
+
if (a[m] <= e) l = m + 1; else r = m;
|
|
1144
|
+
}
|
|
1145
|
+
return a.splice(i, l - i);
|
|
1109
1146
|
}
|
|
1147
|
+
}
|
|
1110
1148
|
|
|
1111
|
-
|
|
1149
|
+
function dt_read_string(byte_array) {
|
|
1150
|
+
return new TextDecoder().decode(new Uint8Array(byte_array.splice(0, dt_read_varint(byte_array))))
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
function dt_read_varint(byte_array) {
|
|
1154
|
+
let result = 0
|
|
1155
|
+
let shift = 0
|
|
1156
|
+
while (true) {
|
|
1157
|
+
if (byte_array.length === 0) throw new Error("byte array does not contain varint")
|
|
1158
|
+
|
|
1159
|
+
let byte_val = byte_array.shift()
|
|
1160
|
+
result |= (byte_val & 0x7f) << shift
|
|
1161
|
+
if ((byte_val & 0x80) == 0) return result
|
|
1162
|
+
shift += 7
|
|
1163
|
+
}
|
|
1112
1164
|
}
|
|
1113
1165
|
|
|
1114
1166
|
function dt_create_bytes(version, parents, pos, del, ins) {
|
|
@@ -1772,6 +1824,52 @@ function apply_patch(obj, range, content) {
|
|
|
1772
1824
|
}
|
|
1773
1825
|
}
|
|
1774
1826
|
|
|
1827
|
+
class RangeSet {
|
|
1828
|
+
constructor() {
|
|
1829
|
+
this.ranges = []
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
add_range(low_inclusive, high_inclusive) {
|
|
1833
|
+
if (low_inclusive > high_inclusive) return
|
|
1834
|
+
|
|
1835
|
+
const startIndex = this._bs(mid => this.ranges[mid][1] >= low_inclusive - 1, this.ranges.length, true)
|
|
1836
|
+
const endIndex = this._bs(mid => this.ranges[mid][0] <= high_inclusive + 1, -1, false)
|
|
1837
|
+
|
|
1838
|
+
if (startIndex > endIndex) {
|
|
1839
|
+
this.ranges.splice(startIndex, 0, [low_inclusive, high_inclusive])
|
|
1840
|
+
} else {
|
|
1841
|
+
const mergedLow = Math.min(low_inclusive, this.ranges[startIndex][0])
|
|
1842
|
+
const mergedHigh = Math.max(high_inclusive, this.ranges[endIndex][1])
|
|
1843
|
+
const removeCount = endIndex - startIndex + 1
|
|
1844
|
+
this.ranges.splice(startIndex, removeCount, [mergedLow, mergedHigh])
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
has(x) {
|
|
1849
|
+
var index = this._bs(mid => this.ranges[mid][0] <= x, -1, false)
|
|
1850
|
+
return index !== -1 && x <= this.ranges[index][1]
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
_bs(condition, defaultR, moveLeft) {
|
|
1854
|
+
let low = 0
|
|
1855
|
+
let high = this.ranges.length - 1
|
|
1856
|
+
let result = defaultR
|
|
1857
|
+
|
|
1858
|
+
while (low <= high) {
|
|
1859
|
+
const mid = Math.floor((low + high) / 2)
|
|
1860
|
+
if (condition(mid)) {
|
|
1861
|
+
result = mid
|
|
1862
|
+
if (moveLeft) high = mid - 1
|
|
1863
|
+
else low = mid + 1
|
|
1864
|
+
} else {
|
|
1865
|
+
if (moveLeft) low = mid + 1
|
|
1866
|
+
else high = mid - 1
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
return result
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1775
1873
|
braid_text.get_resource = get_resource
|
|
1776
1874
|
|
|
1777
1875
|
braid_text.encode_filename = encode_filename
|
|
@@ -1781,8 +1879,10 @@ braid_text.get_files_for_key = get_files_for_key
|
|
|
1781
1879
|
braid_text.dt_get = dt_get
|
|
1782
1880
|
braid_text.dt_get_patches = dt_get_patches
|
|
1783
1881
|
braid_text.dt_parse = dt_parse
|
|
1882
|
+
braid_text.dt_get_local_version = dt_get_local_version
|
|
1784
1883
|
braid_text.dt_create_bytes = dt_create_bytes
|
|
1785
1884
|
|
|
1786
1885
|
braid_text.decode_version = decode_version
|
|
1886
|
+
braid_text.RangeSet = RangeSet
|
|
1787
1887
|
|
|
1788
1888
|
module.exports = braid_text
|
package/package.json
CHANGED
package/test/test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
let { Doc } = require("diamond-types-node")
|
|
3
3
|
let braid_text = require('../index.js')
|
|
4
|
-
let {dt_get, dt_get_patches, dt_parse, dt_create_bytes} = braid_text
|
|
4
|
+
let {dt_get, dt_get_patches, dt_parse, dt_create_bytes, dt_get_local_version, RangeSet} = braid_text
|
|
5
5
|
|
|
6
6
|
process.on("unhandledRejection", (x) =>
|
|
7
7
|
console.log(`unhandledRejection: ${x.stack ?? x}`)
|
|
@@ -12,43 +12,138 @@ process.on("uncaughtException", (x) =>
|
|
|
12
12
|
|
|
13
13
|
braid_text.db_folder = null
|
|
14
14
|
|
|
15
|
-
async function
|
|
15
|
+
async function test_db() {
|
|
16
16
|
braid_text.db_folder = './braid-text-db'
|
|
17
17
|
var key = Math.random().toString(36).slice(2)
|
|
18
18
|
await braid_text.put(key, {version: ['a-0'], body: 'A'})
|
|
19
|
-
await braid_text.put(key, {version: ['a-
|
|
20
|
-
await braid_text.revert(key, ['a-1'])
|
|
19
|
+
await braid_text.put(key, {version: ['a-2'], parents: ['a-0'], patches: [{range: '[1:1]', content: 'B'}]})
|
|
21
20
|
delete braid_text.cache[key]
|
|
22
21
|
var {version, body} = await braid_text.get(key, {})
|
|
23
|
-
if (version[0] != 'a-0') throw new Error('revert error: wrong version')
|
|
24
|
-
if (body != 'A') throw new Error('revert error: wrong text')
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
if ('AC' !== await braid_text.get(key)) throw new Error('revert error: wrong text')
|
|
28
|
-
await braid_text.revert(key, ['b-0'])
|
|
29
|
-
if ('A' !== await braid_text.get(key)) throw new Error('revert error: wrong text')
|
|
30
|
-
delete braid_text.cache[key]
|
|
31
|
-
var {version, body} = await braid_text.get(key, {})
|
|
32
|
-
if (version[0] != 'a-0') throw new Error('revert error: wrong version')
|
|
33
|
-
if (body != 'A') throw new Error('revert error: wrong text')
|
|
23
|
+
if (body != 'AB') throw new Error('db error')
|
|
34
24
|
|
|
35
25
|
braid_text.db_folder = null
|
|
36
26
|
}
|
|
37
27
|
|
|
28
|
+
async function test_dt_get_local_version() {
|
|
29
|
+
for (var tt = 0; tt < 100; tt++) {
|
|
30
|
+
var st = Date.now()
|
|
31
|
+
|
|
32
|
+
var doc = new Doc('x')
|
|
33
|
+
var n = 100
|
|
34
|
+
var v_array = []
|
|
35
|
+
var p_array = []
|
|
36
|
+
var agents = ['hi']
|
|
37
|
+
var agent_rangesets = {}
|
|
38
|
+
|
|
39
|
+
for (var i = 0; i < n; i++) {
|
|
40
|
+
// console.log(`i = ${i}`)
|
|
41
|
+
|
|
42
|
+
// Math.randomSeed('seed::::' + i)
|
|
43
|
+
|
|
44
|
+
var agent = agents[0]
|
|
45
|
+
|
|
46
|
+
var seq = null
|
|
47
|
+
if (!agent_rangesets[agent]) agent_rangesets[agent] = new RangeSet()
|
|
48
|
+
var ranges = agent_rangesets[agent].ranges
|
|
49
|
+
if (!ranges.length) {
|
|
50
|
+
seq = Math.floor(Math.random() * 10)
|
|
51
|
+
} else {
|
|
52
|
+
var ii
|
|
53
|
+
if (ranges[0]?.[0] === 0)
|
|
54
|
+
ii = Math.floor(Math.random() * ranges.length)
|
|
55
|
+
else
|
|
56
|
+
ii = Math.floor(Math.random() * (ranges.length + 1)) - 1
|
|
57
|
+
var low = ii < 0 ? 0 : ranges[ii][1] + 1
|
|
58
|
+
var high = ii + 1 < ranges.length ? ranges[ii + 1][0] - 1 : ranges[ii][1] + 10
|
|
59
|
+
seq = Math.random() < 0.8 ? low : low + Math.floor(Math.random() * (high - low + 1))
|
|
60
|
+
}
|
|
61
|
+
agent_rangesets[agent].add_range(seq, seq)
|
|
62
|
+
v_array.push(`${agent}-${seq}`)
|
|
63
|
+
|
|
64
|
+
var parents = []
|
|
65
|
+
var shadow = new Set()
|
|
66
|
+
if (p_array.length) {
|
|
67
|
+
var starting_point = Math.floor(Math.random() * p_array.length)
|
|
68
|
+
parents.push(starting_point)
|
|
69
|
+
for (var p of p_array[starting_point]) shadow.add(p)
|
|
70
|
+
for (var ii = starting_point - 1; ii >= 0 && Math.random() < 0.9; ii--) {
|
|
71
|
+
if (!shadow.has(ii) && Math.random() < 0.5) {
|
|
72
|
+
parents.push(ii)
|
|
73
|
+
shadow.add(ii)
|
|
74
|
+
}
|
|
75
|
+
if (shadow.has(ii))
|
|
76
|
+
for (var p of p_array[ii])
|
|
77
|
+
shadow.add(p)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
p_array.push(parents)
|
|
81
|
+
parents = parents.map(p => v_array[p])
|
|
82
|
+
|
|
83
|
+
let args = [`${agent}-${seq}`, parents, 0, 0, 'x']
|
|
84
|
+
// console.log(args)
|
|
85
|
+
|
|
86
|
+
doc.mergeBytes(dt_create_bytes(...args))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var bytes = doc.toBytes()
|
|
90
|
+
|
|
91
|
+
for (var t = 0; t < 100; t++) {
|
|
92
|
+
// if (t % 10 === 0) console.log(` t = ${t}`)
|
|
93
|
+
|
|
94
|
+
var version = []
|
|
95
|
+
var vv_array = [...v_array]
|
|
96
|
+
while (!version.length || (vv_array.length && Math.random() < 0.9)) {
|
|
97
|
+
version.push(vv_array.splice(Math.floor(Math.random() * vv_array.length), 1)[0])
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
var local_new = dt_get_local_version(bytes, version)
|
|
101
|
+
var local_old = old_dt_get_local_version(bytes, version)
|
|
102
|
+
|
|
103
|
+
if (local_new.some((x, i) => x != local_old[i])) {
|
|
104
|
+
throw new Error('bad!')
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log(`[tt=${tt}] total T = ${Date.now() - st}`)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function old_dt_get_local_version(bytes, version) {
|
|
113
|
+
var [_agents, versions, _parentss] = dt_parse([...bytes])
|
|
114
|
+
|
|
115
|
+
var frontier = new Set(version)
|
|
116
|
+
|
|
117
|
+
var local_version = []
|
|
118
|
+
for (var i = 0; i < versions.length; i++) {
|
|
119
|
+
var v = versions[i].join("-")
|
|
120
|
+
if (frontier.has(v)) {
|
|
121
|
+
local_version.push(i)
|
|
122
|
+
frontier.delete(v)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (frontier.size) throw new Error(`version not found: ${version}`)
|
|
127
|
+
|
|
128
|
+
return local_version
|
|
129
|
+
}
|
|
130
|
+
|
|
38
131
|
async function main() {
|
|
39
132
|
let best_seed = NaN
|
|
40
133
|
let best_n = Infinity
|
|
41
134
|
let base = Math.floor(Math.random() * 10000000)
|
|
42
135
|
let st = Date.now()
|
|
43
136
|
|
|
44
|
-
await
|
|
137
|
+
await test_dt_get_local_version()
|
|
138
|
+
|
|
139
|
+
await test_db()
|
|
45
140
|
|
|
46
141
|
let og_log = console.log
|
|
47
142
|
console.log = () => {}
|
|
48
143
|
for (let t = 0; t < 10000; t++) {
|
|
49
144
|
let seed = base + t
|
|
50
145
|
// for (let t = 0; t < 1; t++) {
|
|
51
|
-
|
|
146
|
+
// let seed = 403279
|
|
52
147
|
|
|
53
148
|
og_log(`t = ${t}, seed = ${seed}, best_n = ${best_n} @ ${best_seed}`)
|
|
54
149
|
Math.randomSeed(seed)
|
|
@@ -96,14 +191,6 @@ async function main() {
|
|
|
96
191
|
await braid_text.put(key, y)
|
|
97
192
|
y.validate_already_seen_versions = true
|
|
98
193
|
await braid_text.put(key, y)
|
|
99
|
-
|
|
100
|
-
// test revert
|
|
101
|
-
var range = x.range.match(/\d+/g).map((x) => parseInt(x))
|
|
102
|
-
var change_count = [...x.content].length + range[1] - range[0]
|
|
103
|
-
await braid_text.revert(key, [`${actor}-${seq + 1 - change_count}`])
|
|
104
|
-
var new_text = await braid_text.get(key)
|
|
105
|
-
if (old_text !== new_text) throw new Error('revert failed!')
|
|
106
|
-
await braid_text.put(key, y)
|
|
107
194
|
}
|
|
108
195
|
}
|
|
109
196
|
await dt_to_braid(doc, 'doc')
|
|
@@ -134,16 +221,7 @@ async function main() {
|
|
|
134
221
|
await braid_text.get('middle_doc', {peer: 'sim', subscribe: async update => {
|
|
135
222
|
if (first_time) {
|
|
136
223
|
first_time = false
|
|
137
|
-
if (update.body !== await braid_text.get('middle_doc')) fail(new Error('
|
|
138
|
-
|
|
139
|
-
var x = await braid_text.get('middle_doc', {})
|
|
140
|
-
await braid_text.put('middle_doc', {peer: 'sim', version: ['sim-0'], parents: x.version, patches: [{content: 'A', range: '[0:0]'}]})
|
|
141
|
-
await braid_text.put('middle_doc', {peer: 'other', merge_type: 'dt', version: ['other-0'], parents: [], patches: [{content: 'B', range: '[0:0]'}]})
|
|
142
|
-
await braid_text.put('middle_doc', {peer: 'sim', version: ['sim-1'], parents: ['sim-0'], patches: [{content: 'b', range: '[0:0]'}]})
|
|
143
|
-
await braid_text.put('middle_doc', {peer: 'sim', version: ['sim-2'], parents: ['sim-1'], patches: [{content: 'c', range: '[0:0]'}]})
|
|
144
|
-
await braid_text.revert('middle_doc', ['sim-0'])
|
|
145
|
-
await braid_text.revert('middle_doc', ['other-0'])
|
|
146
|
-
|
|
224
|
+
if (update.body !== await braid_text.get('middle_doc')) fail(new Error('simpleton fail'))
|
|
147
225
|
done()
|
|
148
226
|
}
|
|
149
227
|
}})
|