braidfs 0.0.136 → 0.0.138

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.
Files changed (2) hide show
  1. package/index.js +98 -80
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -12,6 +12,8 @@ function is_binary(filename) {
12
12
  }
13
13
 
14
14
  braid_fetch.set_fetch(fetch_http2)
15
+ braid_text.braid_fetch.set_fetch(fetch_http2)
16
+ braid_blob.braid_fetch.set_fetch(fetch_http2)
15
17
 
16
18
  var sync_base = `${require('os').homedir()}/http`
17
19
  // Check for --sync-base argument (hidden for testing)
@@ -435,8 +437,8 @@ function sync_url(url) {
435
437
  if (!sync_url.cache[path]) {
436
438
  // console.log(`sync_url: ${url}`)
437
439
 
438
- var self = {url},
439
- freed = false,
440
+ var self = {url,
441
+ ac: new AbortController()},
440
442
  aborts = new Set()
441
443
  var wait_promise = Promise.resolve()
442
444
  var wait_on = p => {
@@ -451,7 +453,7 @@ function sync_url(url) {
451
453
  }
452
454
  if (!unsync_url.cache) unsync_url.cache = {}
453
455
  unsync_url.cache[path] = async () => {
454
- freed = true
456
+ self.ac.abort()
455
457
  await self.disconnect?.()
456
458
  await wait_promise
457
459
 
@@ -473,6 +475,8 @@ function sync_url(url) {
473
475
 
474
476
  sync_url.cache[path] = (async () => {
475
477
  self.merge_type = await detect_merge_type()
478
+ if (self.ac.signal.aborted) return
479
+
476
480
  if (self.merge_type === 'dt') {
477
481
  return await (sync_url.chain = sync_url.chain.then(init))
478
482
  } else if (self.merge_type === 'aww') {
@@ -493,32 +497,46 @@ function sync_url(url) {
493
497
 
494
498
  if (meta.merge_type) return meta.merge_type
495
499
  } catch (e) {}
496
- if (freed) return
497
-
498
- var res = await braid_fetch(url, {
499
- method: 'HEAD',
500
- retry: () => true,
501
- // braid_fetch will await this function on each reconnect when retrying
502
- parents: async () => reconnect_rate_limiter.get_turn(url),
503
- // version needed to force Merge-Type return header
504
- version: [],
505
- headers: {
506
- // needed for braid.org routing
507
- Accept: 'text/plain',
508
- // in case it supports dt, so it doesn't give us "simpleton"
509
- 'Merge-Type': 'dt',
510
- }
511
- })
500
+ if (self.ac.signal.aborted) return
501
+
502
+ var retry_count = 0
503
+ while (true) {
504
+ try {
505
+ var res = await braid_fetch(url, {
506
+ signal: self.ac.signal,
507
+ method: 'HEAD',
508
+ retry: () => true,
509
+ // braid_fetch will await this function on each reconnect when retrying
510
+ parents: async () => reconnect_rate_limiter.get_turn(url),
511
+ // version needed to force Merge-Type return header
512
+ version: [],
513
+ headers: {
514
+ // needed for braid.org routing
515
+ Accept: 'text/plain',
516
+ // in case it supports dt, so it doesn't give us "simpleton"
517
+ 'Merge-Type': 'dt',
518
+ }
519
+ })
520
+ if (self.ac.signal.aborted) return
512
521
 
513
- var merge_type = res.headers.get('merge-type')
514
- if (merge_type) return merge_type
522
+ var merge_type = res.headers.get('merge-type')
523
+ if (merge_type) return merge_type
524
+ } catch (e) {
525
+ if (e.name !== 'AbortError') throw e
526
+ }
527
+ if (self.ac.signal.aborted) return
515
528
 
516
- throw `failed to get merge type for ${url}`
529
+ // Retry with increasing delays: 1s, 2s, 3s, 3s, 3s...
530
+ var delay = Math.min(++retry_count, 3)
531
+ console.log(`retrying in ${delay}s: ${url} after error: no merge-type header`)
532
+ await new Promise(r => setTimeout(r, delay * 1000))
533
+ if (self.ac.signal.aborted) return
534
+ }
517
535
  }
518
536
 
519
537
  async function init_binary_sync() {
520
538
  await ensure_path_stuff()
521
- if (freed) return
539
+ if (self.ac.signal.aborted) return
522
540
 
523
541
  console.log(`init_binary_sync: ${url}`)
524
542
 
@@ -538,29 +556,29 @@ function sync_url(url) {
538
556
  Object.assign(self, JSON.parse(
539
557
  await require('fs').promises.readFile(meta_path, 'utf8')))
540
558
  } catch (e) {}
541
- if (freed) return
559
+ if (self.ac.signal.aborted) return
542
560
 
543
561
  if (!self.peer) self.peer = Math.random().toString(36).slice(2)
544
562
  })
545
- if (freed) return
563
+ if (self.ac.signal.aborted) return
546
564
 
547
565
  self.signal_file_needs_reading = async () => {
548
566
  await within_fiber(fullpath, async () => {
549
567
  try {
550
- if (freed) return
568
+ if (self.ac.signal.aborted) return
551
569
 
552
570
  var fullpath = await get_fullpath()
553
- if (freed) return
571
+ if (self.ac.signal.aborted) return
554
572
 
555
573
  var stat = await require('fs').promises.stat(fullpath, { bigint: true })
556
- if (freed) return
574
+ if (self.ac.signal.aborted) return
557
575
 
558
576
  if (self.file_mtimeNs_str !== '' + stat.mtimeNs) {
559
577
  var data = await require('fs').promises.readFile(fullpath, { encoding: 'utf8' })
560
- if (freed) return
578
+ if (self.ac.signal.aborted) return
561
579
 
562
580
  await braid_blob.put(url, data, { skip_write: true })
563
- if (freed) return
581
+ if (self.ac.signal.aborted) return
564
582
 
565
583
  self.file_mtimeNs_str = '' + stat.mtimeNs
566
584
  await save_meta()
@@ -576,7 +594,7 @@ function sync_url(url) {
576
594
  read: async (_key) => {
577
595
  return await within_fiber(fullpath, async () => {
578
596
  var fullpath = await get_fullpath()
579
- if (freed) return
597
+ if (self.ac.signal.aborted) return
580
598
 
581
599
  try {
582
600
  return await require('fs').promises.readFile(fullpath)
@@ -589,25 +607,25 @@ function sync_url(url) {
589
607
  write: async (_key, data) => {
590
608
  return await within_fiber(fullpath, async () => {
591
609
  var fullpath = await get_fullpath()
592
- if (freed) return
610
+ if (self.ac.signal.aborted) return
593
611
 
594
612
  try {
595
613
  var temp = `${temp_folder}/${Math.random().toString(36).slice(2)}`
596
614
  await require('fs').promises.writeFile(temp, data)
597
- if (freed) return
615
+ if (self.ac.signal.aborted) return
598
616
 
599
617
  var stat = await require('fs').promises.stat(temp, { bigint: true })
600
- if (freed) return
618
+ if (self.ac.signal.aborted) return
601
619
 
602
620
  await require('fs').promises.rename(temp, fullpath)
603
- if (freed) return
621
+ if (self.ac.signal.aborted) return
604
622
 
605
623
  self.file_mtimeNs_str = '' + stat.mtimeNs
606
624
  await save_meta()
607
- if (freed) return
625
+ if (self.ac.signal.aborted) return
608
626
 
609
627
  if (self.file_read_only !== null && await is_read_only(fullpath) !== self.file_read_only) {
610
- if (freed) return
628
+ if (self.ac.signal.aborted) return
611
629
  await set_read_only(fullpath, self.file_read_only)
612
630
  }
613
631
  } catch (e) {
@@ -619,7 +637,7 @@ function sync_url(url) {
619
637
  delete: async (_key) => {
620
638
  return await within_fiber(fullpath, async () => {
621
639
  var fullpath = await get_fullpath()
622
- if (freed) return
640
+ if (self.ac.signal.aborted) return
623
641
 
624
642
  try {
625
643
  await require('fs').promises.unlink(fullpath)
@@ -633,7 +651,7 @@ function sync_url(url) {
633
651
  var ac
634
652
  function start_sync() {
635
653
  if (ac) ac.abort()
636
- if (freed) return
654
+ if (self.ac.signal.aborted) return
637
655
 
638
656
  var closed = false
639
657
  ac = new AbortController()
@@ -655,18 +673,18 @@ function sync_url(url) {
655
673
  },
656
674
  on_pre_connect: () => reconnect_rate_limiter.get_turn(url),
657
675
  on_res: async res => {
658
- if (freed) return
676
+ if (self.ac.signal.aborted) return
659
677
  reconnect_rate_limiter.on_conn(url)
660
678
  self.file_read_only = res.headers.get('editable') === 'false'
661
679
  console.log(`connected to ${url}${self.file_read_only ? ' (readonly)' : ''}`)
662
680
 
663
681
  await within_fiber(fullpath, async () => {
664
682
  var fullpath = await get_fullpath()
665
- if (freed) return
683
+ if (self.ac.signal.aborted) return
666
684
 
667
685
  try {
668
686
  if (await is_read_only(fullpath) !== self.file_read_only) {
669
- if (freed) return
687
+ if (self.ac.signal.aborted) return
670
688
  await set_read_only(fullpath, self.file_read_only)
671
689
  }
672
690
  } catch (e) {}
@@ -688,23 +706,23 @@ function sync_url(url) {
688
706
  }
689
707
 
690
708
  async function ensure_path_stuff() {
691
- if (freed) return
709
+ if (self.ac.signal.aborted) return
692
710
 
693
711
  // if we're accessing /blah/index, it will be normalized to /blah,
694
712
  // but we still want to create a directory out of blah in this case
695
713
  if (wasnt_normal && !(await is_dir(fullpath))) {
696
- if (freed) return
714
+ if (self.ac.signal.aborted) return
697
715
  await ensure_path(fullpath)
698
716
  }
699
- if (freed) return
717
+ if (self.ac.signal.aborted) return
700
718
 
701
719
  await ensure_path(require("path").dirname(fullpath))
702
- if (freed) return
720
+ if (self.ac.signal.aborted) return
703
721
  }
704
722
 
705
723
  async function init() {
706
724
  await ensure_path_stuff()
707
- if (freed) return
725
+ if (self.ac.signal.aborted) return
708
726
 
709
727
  self.peer = Math.random().toString(36).slice(2)
710
728
  self.local_edit_counter = 0
@@ -751,13 +769,13 @@ function sync_url(url) {
751
769
  }
752
770
 
753
771
  self.signal_file_needs_reading = () => {
754
- if (freed) return
772
+ if (self.ac.signal.aborted) return
755
773
  file_needs_reading = true
756
774
  file_loop_pump()
757
775
  }
758
776
 
759
777
  self.signal_file_needs_writing = (just_meta_file) => {
760
- if (freed) return
778
+ if (self.ac.signal.aborted) return
761
779
 
762
780
  if (!just_meta_file) file_needs_writing = true
763
781
  else if (just_meta_file && !file_needs_writing)
@@ -770,16 +788,16 @@ function sync_url(url) {
770
788
  do_investigating_disconnects_log(url, 'before within_fiber')
771
789
 
772
790
  await within_fiber(fullpath, async () => {
773
- if (freed) return
791
+ if (self.ac.signal.aborted) return
774
792
  var fullpath = await get_fullpath()
775
- if (freed) return
793
+ if (self.ac.signal.aborted) return
776
794
  if (await wait_on(require('fs').promises.access(meta_path).then(
777
795
  () => 1, () => 0))) {
778
- if (freed) return
796
+ if (self.ac.signal.aborted) return
779
797
 
780
798
  // meta file exists
781
799
  let meta = JSON.parse(await wait_on(require('fs').promises.readFile(meta_path, { encoding: 'utf8' })))
782
- if (freed) return
800
+ if (self.ac.signal.aborted) return
783
801
 
784
802
  // destructure stuff from the meta file
785
803
  !({
@@ -800,7 +818,7 @@ function sync_url(url) {
800
818
  try {
801
819
  self.file_last_text = (await wait_on(braid_text.get(url, { version: file_last_version }))).body
802
820
  } catch (e) {
803
- if (freed) return
821
+ if (self.ac.signal.aborted) return
804
822
  // the version from the meta file doesn't exist..
805
823
  if (fullpath === braidfs_config_file) {
806
824
  // in the case of the config file,
@@ -809,44 +827,44 @@ function sync_url(url) {
809
827
  // to the latest
810
828
  console.log(`WARNING: there was an issue with the config file, and it is reverting to the contents at: ${braidfs_config_file}`)
811
829
  var x = await wait_on(braid_text.get(url, {}))
812
- if (freed) return
830
+ if (self.ac.signal.aborted) return
813
831
  file_last_version = x.version
814
832
  self.file_last_text = x.body
815
833
  file_last_digest = sha256(self.file_last_text)
816
834
  } else throw new Error(`sync error: version not found: ${file_last_version}`)
817
835
  }
818
- if (freed) return
836
+ if (self.ac.signal.aborted) return
819
837
 
820
838
  file_needs_writing = !v_eq(file_last_version, (await wait_on(braid_text.get(url, {}))).version)
821
- if (freed) return
839
+ if (self.ac.signal.aborted) return
822
840
 
823
841
  // sanity check
824
842
  if (file_last_digest && sha256(self.file_last_text) != file_last_digest) throw new Error('file_last_text does not match file_last_digest')
825
843
  } else if (await wait_on(require('fs').promises.access(fullpath).then(() => 1, () => 0))) {
826
- if (freed) return
844
+ if (self.ac.signal.aborted) return
827
845
  // file exists, but not meta file
828
846
  file_last_version = []
829
847
  self.file_last_text = ''
830
848
  }
831
849
  })
832
- if (freed) return
850
+ if (self.ac.signal.aborted) return
833
851
 
834
852
  // DEBUGGING HACK ID: L04LPFHQ1M -- INVESTIGATING DISCONNECTS
835
853
  do_investigating_disconnects_log(url, 'after within_fiber')
836
854
 
837
855
  await file_loop_pump()
838
856
  async function file_loop_pump() {
839
- if (freed) return
857
+ if (self.ac.signal.aborted) return
840
858
  if (file_loop_pump_lock) return
841
859
  file_loop_pump_lock++
842
860
 
843
861
  await within_fiber(fullpath, async () => {
844
862
  var fullpath = await get_fullpath()
845
- if (freed) return
863
+ if (self.ac.signal.aborted) return
846
864
 
847
865
  while (file_needs_reading || file_needs_writing) {
848
866
  async function write_meta_file() {
849
- if (freed) return
867
+ if (self.ac.signal.aborted) return
850
868
  await wait_on(require('fs').promises.writeFile(meta_path, JSON.stringify({
851
869
  merge_type: self.merge_type,
852
870
  version: file_last_version,
@@ -863,7 +881,7 @@ function sync_url(url) {
863
881
 
864
882
  // check if file is missing, and create it if so..
865
883
  if (!(await wait_on(file_exists(fullpath)))) {
866
- if (freed) return
884
+ if (self.ac.signal.aborted) return
867
885
 
868
886
  // console.log(`file not found, creating: ${fullpath}`)
869
887
 
@@ -873,17 +891,17 @@ function sync_url(url) {
873
891
 
874
892
  await wait_on(require('fs').promises.writeFile(fullpath, self.file_last_text))
875
893
  }
876
- if (freed) return
894
+ if (self.ac.signal.aborted) return
877
895
 
878
896
  if (self.file_read_only === null) try { self.file_read_only = await wait_on(is_read_only(fullpath)) } catch (e) { }
879
- if (freed) return
897
+ if (self.ac.signal.aborted) return
880
898
 
881
899
  let text = await wait_on(require('fs').promises.readFile(
882
900
  fullpath, { encoding: 'utf8' }))
883
- if (freed) return
901
+ if (self.ac.signal.aborted) return
884
902
 
885
903
  var stat = await wait_on(require('fs').promises.stat(fullpath, { bigint: true }))
886
- if (freed) return
904
+ if (self.ac.signal.aborted) return
887
905
 
888
906
  var patches = diff(self.file_last_text, text)
889
907
  if (patches.length) {
@@ -901,13 +919,13 @@ function sync_url(url) {
901
919
  add_to_version_cache(text, version)
902
920
 
903
921
  await wait_on(braid_text.put(url, { version, parents, patches, merge_type: 'dt' }))
904
- if (freed) return
922
+ if (self.ac.signal.aborted) return
905
923
 
906
924
  // DEBUGGING HACK ID: L04LPFHQ1M -- INVESTIGATING DISCONNECTS
907
925
  require('fs').appendFileSync(investigating_disconnects_log, `${Date.now()}:${url} -- file edited (${self.investigating_disconnects_thinks_connected})\n`)
908
926
 
909
927
  await write_meta_file()
910
- if (freed) return
928
+ if (self.ac.signal.aborted) return
911
929
  } else {
912
930
  add_to_version_cache(text, file_last_version)
913
931
 
@@ -924,16 +942,16 @@ function sync_url(url) {
924
942
  if (file_needs_writing === 'just_meta_file') {
925
943
  file_needs_writing = false
926
944
  await write_meta_file()
927
- if (freed) return
945
+ if (self.ac.signal.aborted) return
928
946
  } else if (file_needs_writing) {
929
947
  file_needs_writing = false
930
948
  let { version, body } = await wait_on(braid_text.get(url, {}))
931
- if (freed) return
949
+ if (self.ac.signal.aborted) return
932
950
  if (!v_eq(version, file_last_version)) {
933
951
  // let's do a final check to see if anything has changed
934
952
  // before writing out a new version of the file
935
953
  let text = await wait_on(require('fs').promises.readFile(fullpath, { encoding: 'utf8' }))
936
- if (freed) return
954
+ if (self.ac.signal.aborted) return
937
955
  if (self.file_last_text != text) {
938
956
  // if the text is different, let's read it first..
939
957
  file_needs_reading = true
@@ -946,27 +964,27 @@ function sync_url(url) {
946
964
  add_to_version_cache(body, version)
947
965
 
948
966
  try { if (await wait_on(is_read_only(fullpath))) await wait_on(set_read_only(fullpath, false)) } catch (e) { }
949
- if (freed) return
967
+ if (self.ac.signal.aborted) return
950
968
 
951
969
  file_last_version = version
952
970
  self.file_last_text = body
953
971
  self.last_touch = Date.now()
954
972
  await wait_on(require('fs').promises.writeFile(fullpath, self.file_last_text))
955
- if (freed) return
973
+ if (self.ac.signal.aborted) return
956
974
  }
957
975
 
958
976
  await write_meta_file()
959
- if (freed) return
977
+ if (self.ac.signal.aborted) return
960
978
 
961
979
  if (await wait_on(is_read_only(fullpath)) !== self.file_read_only) {
962
- if (freed) return
980
+ if (self.ac.signal.aborted) return
963
981
  self.last_touch = Date.now()
964
982
  await wait_on(set_read_only(fullpath, self.file_read_only))
965
983
  }
966
- if (freed) return
984
+ if (self.ac.signal.aborted) return
967
985
 
968
986
  self.file_mtimeNs_str = '' + (await wait_on(require('fs').promises.stat(fullpath, { bigint: true }))).mtimeNs
969
- if (freed) return
987
+ if (self.ac.signal.aborted) return
970
988
 
971
989
  for (var cb of self.file_written_cbs) cb()
972
990
  self.file_written_cbs = []
@@ -1005,7 +1023,7 @@ function sync_url(url) {
1005
1023
  peer: self.peer,
1006
1024
  merge_type: 'dt',
1007
1025
  subscribe: () => {
1008
- if (freed) return
1026
+ if (self.ac.signal.aborted) return
1009
1027
  self.signal_file_needs_writing()
1010
1028
  }
1011
1029
  })
@@ -1033,7 +1051,7 @@ function sync_url(url) {
1033
1051
  do_investigating_disconnects_log(url, `sync.on_res status:${res?.status}`)
1034
1052
  self.investigating_disconnects_thinks_connected = res?.status
1035
1053
 
1036
- if (freed) return
1054
+ if (self.ac.signal.aborted) return
1037
1055
  reconnect_rate_limiter.on_conn(url)
1038
1056
  self.file_read_only = res.headers.get('editable') === 'false'
1039
1057
  console.log(`connected to ${url}${self.file_read_only ? ' (readonly)' : ''}`)
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "braidfs",
3
- "version": "0.0.136",
3
+ "version": "0.0.138",
4
4
  "description": "braid technology synchronizing files and webpages",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braidfs",
7
7
  "homepage": "https://braid.org",
8
8
  "dependencies": {
9
9
  "braid-http": "~1.3.85",
10
- "braid-text": "~0.2.97",
11
- "braid-blob": "~0.0.42",
10
+ "braid-text": "~0.2.99",
11
+ "braid-blob": "~0.0.46",
12
12
  "chokidar": "^4.0.3"
13
13
  },
14
14
  "bin": {