braid-text 0.2.19 → 0.2.21

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 CHANGED
@@ -26,8 +26,8 @@ braid_text.serve = async (req, res, options = {}) => {
26
26
 
27
27
  braid_text.free_cors(res)
28
28
 
29
- function my_end(statusCode, x) {
30
- res.statusCode = statusCode
29
+ function my_end(statusCode, x, statusText, headers) {
30
+ res.writeHead(statusCode, statusText, headers)
31
31
  res.end(x ?? '')
32
32
  }
33
33
 
@@ -134,10 +134,10 @@ braid_text.serve = async (req, res, options = {}) => {
134
134
  let done_my_turn = null
135
135
  prev_put_p = new Promise(
136
136
  (done) =>
137
- (done_my_turn = (statusCode, x) => {
137
+ (done_my_turn = (statusCode, x, statusText, headers) => {
138
138
  waiting_puts--
139
139
  if (braid_text.verbose) console.log(`waiting_puts(after--) = ${waiting_puts}`)
140
- my_end(statusCode, x)
140
+ my_end(statusCode, x, statusText, headers)
141
141
  done()
142
142
  })
143
143
  )
@@ -190,7 +190,7 @@ braid_text.serve = async (req, res, options = {}) => {
190
190
  // - 428 Precondition Required
191
191
  // - pros: the name sounds right
192
192
  // - cons: typically implies that the request was missing an http conditional field like If-Match. that is to say, it implies that the request is missing a precondition, not that the server is missing a precondition
193
- return done_my_turn(425, e.message)
193
+ return done_my_turn(400, e.message, 'Missing Parents', { 'Retry-After': '1' })
194
194
  } else {
195
195
  return done_my_turn(500, "The server failed to apply this version. The error generated was: " + e)
196
196
  }
@@ -580,31 +580,22 @@ braid_text.put = async (key, options) => {
580
580
  await resource.db_delta(resource.doc.getPatchSince(v_before))
581
581
  }
582
582
 
583
- // currently version must be an array with exactly one element, e.g. ["abc-1"]
584
583
  braid_text.revert = async (key, version) => {
585
584
  var resource = (typeof key == 'string') ? await get_resource(key) : key
586
585
 
587
- var [actor, seq] = decode_version(version[0])
588
-
589
- // get version without actor-seq,
590
- // and update actor_seqs
591
- var v = []
592
- for (var [a, s] of Object.entries(resource.actor_seqs)) {
593
- if (a !== actor) v.push(`${a}-${s}`)
594
- else {
595
- if (s < seq) return // nothing to do
596
- else if (seq > 0) {
597
- v.push(`${a}-${seq - 1}`)
598
- resource.actor_seqs[actor] = seq - 1
599
- } else delete resource.actor_seqs[actor]
600
- }
601
- }
602
-
603
586
  // revert dt
604
587
  var old_doc = resource.doc
605
- resource.doc = dt_get(resource.doc, v)
588
+ resource.doc = dt_get(resource.doc, null, null, version)
606
589
  old_doc.free()
607
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
+
608
599
  resource.val = resource.doc.get()
609
600
 
610
601
  // save it
@@ -852,32 +843,47 @@ function dt_get_string(doc, version) {
852
843
  return s
853
844
  }
854
845
 
855
- function dt_get(doc, version, agent = null) {
846
+ function dt_get(doc, version, agent = null, anti_version = null) {
856
847
  if (dt_get.last_doc) dt_get.last_doc.free()
857
848
 
858
849
  let bytes = doc.toBytes()
859
850
  dt_get.last_doc = doc = Doc.fromBytes(bytes, agent)
860
851
 
861
852
  let [_agents, versions, parentss] = dt_parse([...bytes])
862
-
863
- let frontier = new Set(version)
864
-
865
- let local_version = []
866
- for (let i = 0; i < versions.length; i++) {
867
- var v = versions[i].join("-")
868
- if (frontier.has(v)) {
869
- local_version.push(i)
870
- frontier.delete(v)
853
+ if (anti_version) {
854
+ var include_versions = new Set()
855
+ var bad_versions = new Set(anti_version)
856
+
857
+ for (let i = 0; i < versions.length; i++) {
858
+ var v = versions[i].join("-")
859
+ var ps = parentss[i].map(x => x.join('-'))
860
+ if (bad_versions.has(v) || ps.some(x => bad_versions.has(x)))
861
+ bad_versions.add(v)
862
+ else
863
+ include_versions.add(v)
871
864
  }
872
- }
873
-
874
- if (frontier.size) throw new Error(`version not found: ${version}`)
865
+ } else {
866
+ var include_versions = new Set(version)
867
+ var looking_for = new Set(version)
868
+ var local_version = []
869
+
870
+ for (let i = versions.length - 1; i >= 0; i--) {
871
+ var v = versions[i].join("-")
872
+ var ps = parentss[i].map(x => x.join('-'))
873
+ if (looking_for.has(v)) {
874
+ local_version.push(i)
875
+ looking_for.delete(v)
876
+ }
877
+ if (include_versions.has(v))
878
+ ps.forEach(x => include_versions.add(x))
879
+ }
880
+ local_version.reverse()
875
881
 
876
- dt_get.last_local_version = local_version = new Uint32Array(local_version)
882
+ // NOTE: currently used by braid-chrome in dt.js at the bottom
883
+ dt_get.last_local_version = new Uint32Array(local_version)
877
884
 
878
- let after_versions = {}
879
- let [_, after_versions_array, __] = dt_parse([...doc.getPatchSince(local_version)])
880
- for (let v of after_versions_array) after_versions[v.join("-")] = true
885
+ if (looking_for.size) throw new Error(`version not found: ${version}`)
886
+ }
881
887
 
882
888
  let new_doc = new Doc(agent)
883
889
  let op_runs = doc.getOpsSince([])
@@ -900,12 +906,12 @@ function dt_get(doc, version, agent = null) {
900
906
  ) {
901
907
  for (; i < I; i++) {
902
908
  let version = versions[i].join("-")
903
- if (after_versions[version]) continue
909
+ if (!include_versions.has(version)) continue
904
910
  let og_i = i
905
911
  let content = []
906
912
  if (op_run.content?.[i - base_i]) content.push(op_run.content[i - base_i])
907
913
  if (!!op_run.content === op_run.fwd)
908
- while (i + 1 < I && !after_versions[versions[i + 1].join("-")]) {
914
+ while (i + 1 < I && include_versions.has(versions[i + 1].join("-"))) {
909
915
  i++
910
916
  if (op_run.content?.[i - base_i]) content.push(op_run.content[i - base_i])
911
917
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-text",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "description": "Library for collaborative text over http using braid.",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braid-text",
package/test/test.html CHANGED
@@ -238,4 +238,32 @@ runTest(
238
238
  '19'
239
239
  )
240
240
 
241
+ runTest(
242
+ "test retry when parents not there..",
243
+ async () => {
244
+ return await new Promise(done => {
245
+ var count = 0
246
+ var key = 'test-' + Math.random().toString(36).slice(2)
247
+ var a = new AbortController()
248
+ braid_fetch(`/${key}`, {
249
+ signal: a.signal,
250
+ multiplex: false,
251
+ method: 'PUT',
252
+ version: ['hi-3'],
253
+ parents: ['hi-1'],
254
+ body: 'xx',
255
+ onFetch: () => {
256
+ count++
257
+ if (count === 2) {
258
+ done('retried!')
259
+ a.abort()
260
+ }
261
+ },
262
+ retry: true
263
+ })
264
+ })
265
+ },
266
+ 'retried!'
267
+ )
268
+
241
269
  </script>
package/test/test.js CHANGED
@@ -4,10 +4,10 @@ let braid_text = require('../index.js')
4
4
  let {dt_get, dt_get_patches, dt_parse, dt_create_bytes} = braid_text
5
5
 
6
6
  process.on("unhandledRejection", (x) =>
7
- console.log(`unhandledRejection: ${x.stack}`)
7
+ console.log(`unhandledRejection: ${x.stack ?? x}`)
8
8
  )
9
9
  process.on("uncaughtException", (x) =>
10
- console.log(`uncaughtException: ${x.stack}`)
10
+ console.log(`uncaughtException: ${x.stack ?? x}`)
11
11
  )
12
12
 
13
13
  braid_text.db_folder = null
@@ -48,7 +48,7 @@ async function main() {
48
48
  for (let t = 0; t < 10000; t++) {
49
49
  let seed = base + t
50
50
  // for (let t = 0; t < 1; t++) {
51
- // let seed = 7375800
51
+ // let seed = 2746153
52
52
 
53
53
  og_log(`t = ${t}, seed = ${seed}, best_n = ${best_n} @ ${best_seed}`)
54
54
  Math.randomSeed(seed)
@@ -80,7 +80,6 @@ async function main() {
80
80
  for (let x of dt_get_patches(doc)) {
81
81
  var resource = await braid_text.get_resource(key)
82
82
  var [actor, seq] = braid_text.decode_version(x.version)
83
- var pre_seq = resource.actor_seqs[actor]
84
83
  var old_text = await braid_text.get(key)
85
84
 
86
85
  console.log(`x = `, x)
@@ -99,7 +98,9 @@ async function main() {
99
98
  await braid_text.put(key, y)
100
99
 
101
100
  // test revert
102
- await braid_text.revert(key, [`${actor}-${(pre_seq ?? -1) + 1}`])
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}`])
103
104
  var new_text = await braid_text.get(key)
104
105
  if (old_text !== new_text) throw new Error('revert failed!')
105
106
  await braid_text.put(key, y)