@powersync/service-module-mongodb-storage 0.18.3 → 0.19.0

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 (137) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.d.ts +3 -0
  3. package/dist/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.js +41 -0
  4. package/dist/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.js.map +1 -0
  5. package/dist/storage/MongoBucketStorage.d.ts +5 -1
  6. package/dist/storage/MongoBucketStorage.js +5 -1
  7. package/dist/storage/MongoBucketStorage.js.map +1 -1
  8. package/dist/storage/implementation/MongoBucketBatch.d.ts +3 -0
  9. package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
  10. package/dist/storage/implementation/MongoCompactor.d.ts +15 -19
  11. package/dist/storage/implementation/MongoCompactor.js +68 -260
  12. package/dist/storage/implementation/MongoCompactor.js.map +1 -1
  13. package/dist/storage/implementation/MongoStorageProvider.js +26 -3
  14. package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
  15. package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +10 -4
  16. package/dist/storage/implementation/MongoSyncBucketStorage.js +13 -12
  17. package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
  18. package/dist/storage/implementation/MongoWriteCheckpointAPI.d.ts +2 -1
  19. package/dist/storage/implementation/MongoWriteCheckpointAPI.js +146 -34
  20. package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
  21. package/dist/storage/implementation/common/PersistedBatch.d.ts +6 -0
  22. package/dist/storage/implementation/common/PersistedBatch.js +15 -8
  23. package/dist/storage/implementation/common/PersistedBatch.js.map +1 -1
  24. package/dist/storage/implementation/models.d.ts +16 -0
  25. package/dist/storage/implementation/models.js.map +1 -1
  26. package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +11 -2
  27. package/dist/storage/implementation/v1/MongoCompactorV1.js +250 -1
  28. package/dist/storage/implementation/v1/MongoCompactorV1.js.map +1 -1
  29. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +19 -11
  30. package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -1
  31. package/dist/storage/implementation/v1/SingleBucketStoreV1.d.ts +9 -10
  32. package/dist/storage/implementation/v1/SingleBucketStoreV1.js +2 -8
  33. package/dist/storage/implementation/v1/SingleBucketStoreV1.js.map +1 -1
  34. package/dist/storage/implementation/v3/BucketDataContextV3.d.ts +13 -0
  35. package/dist/storage/implementation/v3/BucketDataContextV3.js +23 -0
  36. package/dist/storage/implementation/v3/BucketDataContextV3.js.map +1 -0
  37. package/dist/storage/implementation/v3/MongoBucketBatchV3.js +3 -1
  38. package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -1
  39. package/dist/storage/implementation/v3/MongoChecksumsV3.d.ts +1 -0
  40. package/dist/storage/implementation/v3/MongoChecksumsV3.js +59 -103
  41. package/dist/storage/implementation/v3/MongoChecksumsV3.js.map +1 -1
  42. package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +23 -2
  43. package/dist/storage/implementation/v3/MongoCompactorV3.js +354 -219
  44. package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
  45. package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.d.ts +5 -0
  46. package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js +12 -11
  47. package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js.map +1 -1
  48. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +5 -3
  49. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +108 -106
  50. package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
  51. package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +5 -2
  52. package/dist/storage/implementation/v3/PersistedBatchV3.js +53 -15
  53. package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -1
  54. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +2 -1
  55. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +3 -0
  56. package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -1
  57. package/dist/storage/implementation/v3/bucket-format.d.ts +10 -1
  58. package/dist/storage/implementation/v3/bucket-format.js +28 -9
  59. package/dist/storage/implementation/v3/bucket-format.js.map +1 -1
  60. package/dist/storage/implementation/v3/chunking.js +3 -1
  61. package/dist/storage/implementation/v3/chunking.js.map +1 -1
  62. package/dist/storage/implementation/v3/models.d.ts +38 -1
  63. package/dist/storage/implementation/v3/models.js.map +1 -1
  64. package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.d.ts +21 -0
  65. package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js +44 -0
  66. package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js.map +1 -0
  67. package/dist/storage/implementation/v3/object-storage/ObjectStorage.d.ts +30 -0
  68. package/dist/storage/implementation/v3/object-storage/ObjectStorage.js +12 -0
  69. package/dist/storage/implementation/v3/object-storage/ObjectStorage.js.map +1 -0
  70. package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.d.ts +70 -0
  71. package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js +146 -0
  72. package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js.map +1 -0
  73. package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.d.ts +42 -0
  74. package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.js +285 -0
  75. package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.js.map +1 -0
  76. package/dist/types/types.d.ts +35 -0
  77. package/dist/types/types.js +35 -1
  78. package/dist/types/types.js.map +1 -1
  79. package/dist/utils/test-utils.js +3 -1
  80. package/dist/utils/test-utils.js.map +1 -1
  81. package/dist/utils/util.d.ts +8 -1
  82. package/dist/utils/util.js +125 -2
  83. package/dist/utils/util.js.map +1 -1
  84. package/package.json +10 -7
  85. package/src/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.ts +55 -0
  86. package/src/storage/MongoBucketStorage.ts +10 -2
  87. package/src/storage/implementation/MongoBucketBatch.ts +4 -0
  88. package/src/storage/implementation/MongoCompactor.ts +90 -314
  89. package/src/storage/implementation/MongoStorageProvider.ts +32 -3
  90. package/src/storage/implementation/MongoSyncBucketStorage.ts +23 -22
  91. package/src/storage/implementation/MongoWriteCheckpointAPI.ts +164 -37
  92. package/src/storage/implementation/common/PersistedBatch.ts +22 -10
  93. package/src/storage/implementation/models.ts +16 -0
  94. package/src/storage/implementation/v1/MongoCompactorV1.ts +292 -8
  95. package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +53 -40
  96. package/src/storage/implementation/v1/SingleBucketStoreV1.ts +18 -27
  97. package/src/storage/implementation/v3/BucketDataContextV3.ts +32 -0
  98. package/src/storage/implementation/v3/MongoBucketBatchV3.ts +3 -1
  99. package/src/storage/implementation/v3/MongoChecksumsV3.ts +75 -105
  100. package/src/storage/implementation/v3/MongoCompactorV3.ts +456 -258
  101. package/src/storage/implementation/v3/MongoStoppedSyncConfigCleanup.ts +21 -19
  102. package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +122 -126
  103. package/src/storage/implementation/v3/PersistedBatchV3.ts +69 -16
  104. package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +5 -0
  105. package/src/storage/implementation/v3/bucket-format.ts +36 -9
  106. package/src/storage/implementation/v3/chunking.ts +3 -1
  107. package/src/storage/implementation/v3/models.ts +40 -1
  108. package/src/storage/implementation/v3/object-storage/BucketDataObjectStorage.ts +54 -0
  109. package/src/storage/implementation/v3/object-storage/ObjectStorage.ts +29 -0
  110. package/src/storage/implementation/v3/object-storage/ObjectStorageLifecycle.ts +171 -0
  111. package/src/storage/implementation/v3/object-storage/S3ObjectStorage.ts +343 -0
  112. package/src/types/types.ts +42 -1
  113. package/src/utils/test-utils.ts +3 -1
  114. package/src/utils/util.ts +182 -4
  115. package/test/src/__snapshots__/storage_sync.test.ts.snap +1 -583
  116. package/test/src/cleanup-stopped-sync-configs.test.ts +24 -1
  117. package/test/src/helpers/MemoryObjectStorage.ts +53 -0
  118. package/test/src/helpers/s3TestFactory.ts +69 -0
  119. package/test/src/object_storage_lifecycle.test.ts +59 -0
  120. package/test/src/setup.ts +6 -1
  121. package/test/src/storage.test.ts +216 -2
  122. package/test/src/storage_compacting.test.ts +176 -187
  123. package/test/src/storage_object_storage_inline_threshold.test.ts +116 -0
  124. package/test/src/storage_s3_checksums.test.ts +191 -0
  125. package/test/src/storage_s3_compaction_lifecycle.test.ts +417 -0
  126. package/test/src/storage_s3_reading.test.ts +526 -0
  127. package/test/src/storage_s3_writing.test.ts +135 -0
  128. package/test/src/storage_sync.test.ts +95 -5
  129. package/tsconfig.tsbuildinfo +1 -1
  130. package/dist/storage/implementation/common/SingleBucketStore.d.ts +0 -54
  131. package/dist/storage/implementation/common/SingleBucketStore.js +0 -3
  132. package/dist/storage/implementation/common/SingleBucketStore.js.map +0 -1
  133. package/dist/storage/implementation/v3/SingleBucketStoreV3.d.ts +0 -18
  134. package/dist/storage/implementation/v3/SingleBucketStoreV3.js +0 -84
  135. package/dist/storage/implementation/v3/SingleBucketStoreV3.js.map +0 -1
  136. package/src/storage/implementation/common/SingleBucketStore.ts +0 -63
  137. package/src/storage/implementation/v3/SingleBucketStoreV3.ts +0 -108
@@ -589,200 +589,6 @@ exports[`sync - mongodb > storage v1 > sync global data 1`] = `
589
589
  ]
590
590
  `;
591
591
 
592
- exports[`sync - mongodb > storage v1 > sync interrupts low-priority buckets on new checkpoints (2) 1`] = `
593
- [
594
- {
595
- "checkpoint": {
596
- "buckets": [
597
- {
598
- "bucket": "b0a[]",
599
- "checksum": -659831575,
600
- "count": 2000,
601
- "priority": 2,
602
- "subscriptions": [
603
- {
604
- "default": 0,
605
- },
606
- ],
607
- },
608
- {
609
- "bucket": "b0b[]",
610
- "checksum": -659831575,
611
- "count": 2000,
612
- "priority": 2,
613
- "subscriptions": [
614
- {
615
- "default": 1,
616
- },
617
- ],
618
- },
619
- {
620
- "bucket": "b1[]",
621
- "checksum": -1096116670,
622
- "count": 1,
623
- "priority": 1,
624
- "subscriptions": [
625
- {
626
- "default": 2,
627
- },
628
- ],
629
- },
630
- ],
631
- "last_op_id": "4001",
632
- "streams": [
633
- {
634
- "errors": [],
635
- "is_default": true,
636
- "name": "b0a",
637
- },
638
- {
639
- "errors": [],
640
- "is_default": true,
641
- "name": "b0b",
642
- },
643
- {
644
- "errors": [],
645
- "is_default": true,
646
- "name": "b1",
647
- },
648
- ],
649
- "write_checkpoint": undefined,
650
- },
651
- },
652
- {
653
- "data": {
654
- "after": "0",
655
- "bucket": "b1[]",
656
- "data": undefined,
657
- "has_more": false,
658
- "next_after": "1",
659
- },
660
- },
661
- {
662
- "partial_checkpoint_complete": {
663
- "last_op_id": "4001",
664
- "priority": 1,
665
- },
666
- },
667
- {
668
- "data": {
669
- "after": "0",
670
- "bucket": "b0a[]",
671
- "data": undefined,
672
- "has_more": true,
673
- "next_after": "2000",
674
- },
675
- },
676
- {
677
- "data": {
678
- "after": "2000",
679
- "bucket": "b0a[]",
680
- "data": undefined,
681
- "has_more": true,
682
- "next_after": "4000",
683
- },
684
- },
685
- {
686
- "checkpoint_diff": {
687
- "last_op_id": "4004",
688
- "removed_buckets": [],
689
- "updated_buckets": [
690
- {
691
- "bucket": "b0a[]",
692
- "checksum": 883076828,
693
- "count": 2001,
694
- "priority": 2,
695
- "subscriptions": [
696
- {
697
- "default": 0,
698
- },
699
- ],
700
- },
701
- {
702
- "bucket": "b0b[]",
703
- "checksum": 883076828,
704
- "count": 2001,
705
- "priority": 2,
706
- "subscriptions": [
707
- {
708
- "default": 1,
709
- },
710
- ],
711
- },
712
- {
713
- "bucket": "b1[]",
714
- "checksum": 1841937527,
715
- "count": 2,
716
- "priority": 1,
717
- "subscriptions": [
718
- {
719
- "default": 2,
720
- },
721
- ],
722
- },
723
- ],
724
- "write_checkpoint": undefined,
725
- },
726
- },
727
- {
728
- "data": {
729
- "after": "1",
730
- "bucket": "b1[]",
731
- "data": undefined,
732
- "has_more": false,
733
- "next_after": "4002",
734
- },
735
- },
736
- {
737
- "partial_checkpoint_complete": {
738
- "last_op_id": "4004",
739
- "priority": 1,
740
- },
741
- },
742
- {
743
- "data": {
744
- "after": "4000",
745
- "bucket": "b0a[]",
746
- "data": undefined,
747
- "has_more": false,
748
- "next_after": "4003",
749
- },
750
- },
751
- {
752
- "data": {
753
- "after": "0",
754
- "bucket": "b0b[]",
755
- "data": undefined,
756
- "has_more": true,
757
- "next_after": "1999",
758
- },
759
- },
760
- {
761
- "data": {
762
- "after": "1999",
763
- "bucket": "b0b[]",
764
- "data": undefined,
765
- "has_more": true,
766
- "next_after": "3999",
767
- },
768
- },
769
- {
770
- "data": {
771
- "after": "3999",
772
- "bucket": "b0b[]",
773
- "data": undefined,
774
- "has_more": false,
775
- "next_after": "4004",
776
- },
777
- },
778
- {
779
- "checkpoint_complete": {
780
- "last_op_id": "4004",
781
- },
782
- },
783
- ]
784
- `;
785
-
786
592
  exports[`sync - mongodb > storage v1 > sync legacy non-raw data 1`] = `
787
593
  [
788
594
  {
@@ -1778,200 +1584,6 @@ exports[`sync - mongodb > storage v2 > sync global data 1`] = `
1778
1584
  ]
1779
1585
  `;
1780
1586
 
1781
- exports[`sync - mongodb > storage v2 > sync interrupts low-priority buckets on new checkpoints (2) 1`] = `
1782
- [
1783
- {
1784
- "checkpoint": {
1785
- "buckets": [
1786
- {
1787
- "bucket": "1#b0a[]",
1788
- "checksum": -659831575,
1789
- "count": 2000,
1790
- "priority": 2,
1791
- "subscriptions": [
1792
- {
1793
- "default": 0,
1794
- },
1795
- ],
1796
- },
1797
- {
1798
- "bucket": "1#b0b[]",
1799
- "checksum": -659831575,
1800
- "count": 2000,
1801
- "priority": 2,
1802
- "subscriptions": [
1803
- {
1804
- "default": 1,
1805
- },
1806
- ],
1807
- },
1808
- {
1809
- "bucket": "1#b1[]",
1810
- "checksum": -1096116670,
1811
- "count": 1,
1812
- "priority": 1,
1813
- "subscriptions": [
1814
- {
1815
- "default": 2,
1816
- },
1817
- ],
1818
- },
1819
- ],
1820
- "last_op_id": "4001",
1821
- "streams": [
1822
- {
1823
- "errors": [],
1824
- "is_default": true,
1825
- "name": "b0a",
1826
- },
1827
- {
1828
- "errors": [],
1829
- "is_default": true,
1830
- "name": "b0b",
1831
- },
1832
- {
1833
- "errors": [],
1834
- "is_default": true,
1835
- "name": "b1",
1836
- },
1837
- ],
1838
- "write_checkpoint": undefined,
1839
- },
1840
- },
1841
- {
1842
- "data": {
1843
- "after": "0",
1844
- "bucket": "1#b1[]",
1845
- "data": undefined,
1846
- "has_more": false,
1847
- "next_after": "1",
1848
- },
1849
- },
1850
- {
1851
- "partial_checkpoint_complete": {
1852
- "last_op_id": "4001",
1853
- "priority": 1,
1854
- },
1855
- },
1856
- {
1857
- "data": {
1858
- "after": "0",
1859
- "bucket": "1#b0a[]",
1860
- "data": undefined,
1861
- "has_more": true,
1862
- "next_after": "2000",
1863
- },
1864
- },
1865
- {
1866
- "data": {
1867
- "after": "2000",
1868
- "bucket": "1#b0a[]",
1869
- "data": undefined,
1870
- "has_more": true,
1871
- "next_after": "4000",
1872
- },
1873
- },
1874
- {
1875
- "checkpoint_diff": {
1876
- "last_op_id": "4004",
1877
- "removed_buckets": [],
1878
- "updated_buckets": [
1879
- {
1880
- "bucket": "1#b0a[]",
1881
- "checksum": 883076828,
1882
- "count": 2001,
1883
- "priority": 2,
1884
- "subscriptions": [
1885
- {
1886
- "default": 0,
1887
- },
1888
- ],
1889
- },
1890
- {
1891
- "bucket": "1#b0b[]",
1892
- "checksum": 883076828,
1893
- "count": 2001,
1894
- "priority": 2,
1895
- "subscriptions": [
1896
- {
1897
- "default": 1,
1898
- },
1899
- ],
1900
- },
1901
- {
1902
- "bucket": "1#b1[]",
1903
- "checksum": 1841937527,
1904
- "count": 2,
1905
- "priority": 1,
1906
- "subscriptions": [
1907
- {
1908
- "default": 2,
1909
- },
1910
- ],
1911
- },
1912
- ],
1913
- "write_checkpoint": undefined,
1914
- },
1915
- },
1916
- {
1917
- "data": {
1918
- "after": "1",
1919
- "bucket": "1#b1[]",
1920
- "data": undefined,
1921
- "has_more": false,
1922
- "next_after": "4002",
1923
- },
1924
- },
1925
- {
1926
- "partial_checkpoint_complete": {
1927
- "last_op_id": "4004",
1928
- "priority": 1,
1929
- },
1930
- },
1931
- {
1932
- "data": {
1933
- "after": "4000",
1934
- "bucket": "1#b0a[]",
1935
- "data": undefined,
1936
- "has_more": false,
1937
- "next_after": "4003",
1938
- },
1939
- },
1940
- {
1941
- "data": {
1942
- "after": "0",
1943
- "bucket": "1#b0b[]",
1944
- "data": undefined,
1945
- "has_more": true,
1946
- "next_after": "1999",
1947
- },
1948
- },
1949
- {
1950
- "data": {
1951
- "after": "1999",
1952
- "bucket": "1#b0b[]",
1953
- "data": undefined,
1954
- "has_more": true,
1955
- "next_after": "3999",
1956
- },
1957
- },
1958
- {
1959
- "data": {
1960
- "after": "3999",
1961
- "bucket": "1#b0b[]",
1962
- "data": undefined,
1963
- "has_more": false,
1964
- "next_after": "4004",
1965
- },
1966
- },
1967
- {
1968
- "checkpoint_complete": {
1969
- "last_op_id": "4004",
1970
- },
1971
- },
1972
- ]
1973
- `;
1974
-
1975
1587
  exports[`sync - mongodb > storage v2 > sync legacy non-raw data 1`] = `
1976
1588
  [
1977
1589
  {
@@ -2967,200 +2579,6 @@ exports[`sync - mongodb > storage v3 > sync global data 1`] = `
2967
2579
  ]
2968
2580
  `;
2969
2581
 
2970
- exports[`sync - mongodb > storage v3 > sync interrupts low-priority buckets on new checkpoints (2) 1`] = `
2971
- [
2972
- {
2973
- "checkpoint": {
2974
- "buckets": [
2975
- {
2976
- "bucket": "b0a.1.1[]",
2977
- "checksum": -659831575,
2978
- "count": 2000,
2979
- "priority": 2,
2980
- "subscriptions": [
2981
- {
2982
- "default": 0,
2983
- },
2984
- ],
2985
- },
2986
- {
2987
- "bucket": "b0b.1.2[]",
2988
- "checksum": -659831575,
2989
- "count": 2000,
2990
- "priority": 2,
2991
- "subscriptions": [
2992
- {
2993
- "default": 1,
2994
- },
2995
- ],
2996
- },
2997
- {
2998
- "bucket": "b1.1.3[]",
2999
- "checksum": -1096116670,
3000
- "count": 1,
3001
- "priority": 1,
3002
- "subscriptions": [
3003
- {
3004
- "default": 2,
3005
- },
3006
- ],
3007
- },
3008
- ],
3009
- "last_op_id": "4001",
3010
- "streams": [
3011
- {
3012
- "errors": [],
3013
- "is_default": true,
3014
- "name": "b0a",
3015
- },
3016
- {
3017
- "errors": [],
3018
- "is_default": true,
3019
- "name": "b0b",
3020
- },
3021
- {
3022
- "errors": [],
3023
- "is_default": true,
3024
- "name": "b1",
3025
- },
3026
- ],
3027
- "write_checkpoint": undefined,
3028
- },
3029
- },
3030
- {
3031
- "data": {
3032
- "after": "0",
3033
- "bucket": "b1.1.3[]",
3034
- "data": undefined,
3035
- "has_more": false,
3036
- "next_after": "1",
3037
- },
3038
- },
3039
- {
3040
- "partial_checkpoint_complete": {
3041
- "last_op_id": "4001",
3042
- "priority": 1,
3043
- },
3044
- },
3045
- {
3046
- "data": {
3047
- "after": "0",
3048
- "bucket": "b0a.1.1[]",
3049
- "data": undefined,
3050
- "has_more": true,
3051
- "next_after": "2000",
3052
- },
3053
- },
3054
- {
3055
- "data": {
3056
- "after": "2000",
3057
- "bucket": "b0a.1.1[]",
3058
- "data": undefined,
3059
- "has_more": true,
3060
- "next_after": "4000",
3061
- },
3062
- },
3063
- {
3064
- "checkpoint_diff": {
3065
- "last_op_id": "4004",
3066
- "removed_buckets": [],
3067
- "updated_buckets": [
3068
- {
3069
- "bucket": "b0a.1.1[]",
3070
- "checksum": 883076828,
3071
- "count": 2001,
3072
- "priority": 2,
3073
- "subscriptions": [
3074
- {
3075
- "default": 0,
3076
- },
3077
- ],
3078
- },
3079
- {
3080
- "bucket": "b0b.1.2[]",
3081
- "checksum": 883076828,
3082
- "count": 2001,
3083
- "priority": 2,
3084
- "subscriptions": [
3085
- {
3086
- "default": 1,
3087
- },
3088
- ],
3089
- },
3090
- {
3091
- "bucket": "b1.1.3[]",
3092
- "checksum": 1841937527,
3093
- "count": 2,
3094
- "priority": 1,
3095
- "subscriptions": [
3096
- {
3097
- "default": 2,
3098
- },
3099
- ],
3100
- },
3101
- ],
3102
- "write_checkpoint": undefined,
3103
- },
3104
- },
3105
- {
3106
- "data": {
3107
- "after": "1",
3108
- "bucket": "b1.1.3[]",
3109
- "data": undefined,
3110
- "has_more": false,
3111
- "next_after": "4002",
3112
- },
3113
- },
3114
- {
3115
- "partial_checkpoint_complete": {
3116
- "last_op_id": "4004",
3117
- "priority": 1,
3118
- },
3119
- },
3120
- {
3121
- "data": {
3122
- "after": "4000",
3123
- "bucket": "b0a.1.1[]",
3124
- "data": undefined,
3125
- "has_more": false,
3126
- "next_after": "4003",
3127
- },
3128
- },
3129
- {
3130
- "data": {
3131
- "after": "0",
3132
- "bucket": "b0b.1.2[]",
3133
- "data": undefined,
3134
- "has_more": true,
3135
- "next_after": "1999",
3136
- },
3137
- },
3138
- {
3139
- "data": {
3140
- "after": "1999",
3141
- "bucket": "b0b.1.2[]",
3142
- "data": undefined,
3143
- "has_more": true,
3144
- "next_after": "3999",
3145
- },
3146
- },
3147
- {
3148
- "data": {
3149
- "after": "3999",
3150
- "bucket": "b0b.1.2[]",
3151
- "data": undefined,
3152
- "has_more": false,
3153
- "next_after": "4004",
3154
- },
3155
- },
3156
- {
3157
- "checkpoint_complete": {
3158
- "last_op_id": "4004",
3159
- },
3160
- },
3161
- ]
3162
- `;
3163
-
3164
2582
  exports[`sync - mongodb > storage v3 > sync legacy non-raw data 1`] = `
3165
2583
  [
3166
2584
  {
@@ -3281,7 +2699,7 @@ exports[`sync - mongodb > storage v3 > sync updates to data query only 2`] = `
3281
2699
  },
3282
2700
  {
3283
2701
  "data": {
3284
- "after": "0",
2702
+ "after": "1",
3285
2703
  "bucket": "by_user.1.1["user1"]",
3286
2704
  "data": [
3287
2705
  {
@@ -1,10 +1,14 @@
1
1
  import { MongoSyncBucketStorageV3 } from '@module/storage/implementation/v3/MongoSyncBucketStorageV3.js';
2
+ import { ObjectStorageLifecycle } from '@module/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js';
3
+ import { mongoTestStorageFactoryGenerator } from '@module/utils/test-utils.js';
2
4
  import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
3
5
  import { test_utils } from '@powersync/service-core-tests';
4
6
  import * as bson from 'bson';
5
7
  import { describe, expect, test } from 'vitest';
6
8
  import { VersionedPowerSyncMongoV3 } from '../../src/storage/implementation/v3/VersionedPowerSyncMongoV3.js';
7
9
  import { ReplicationStreamDocumentV3 } from '../../src/storage/implementation/v3/models.js';
10
+ import { env } from './env.js';
11
+ import { MemoryObjectStorage } from './helpers/MemoryObjectStorage.js';
8
12
  import { INITIALIZED_MONGO_STORAGE_FACTORY } from './util.js';
9
13
 
10
14
  function sourceDescriptor(name: string, options: { objectId?: string } = {}): storage.SourceEntityDescriptor {
@@ -47,7 +51,14 @@ async function cleanupStoppedSyncConfigs(bucketStorage: MongoSyncBucketStorageV3
47
51
 
48
52
  describe('cleanupStoppedSyncConfigs - mongodb', () => {
49
53
  test('cleans up unused stopped sync config storage', async () => {
50
- await using factory = await INITIALIZED_MONGO_STORAGE_FACTORY.factory();
54
+ const objectStorage = new MemoryObjectStorage();
55
+ const storageFactory = mongoTestStorageFactoryGenerator({
56
+ url: env.MONGO_TEST_URL,
57
+ isCI: env.CI,
58
+ supportsMultipleSyncConfigs: true,
59
+ objectStorage
60
+ });
61
+ await using factory = await storageFactory.factory();
51
62
 
52
63
  const first = await factory.updateSyncRules(
53
64
  updateSyncRulesFromYaml(
@@ -149,6 +160,16 @@ streams:
149
160
  await secondWriter.markAllSnapshotDone('2/1');
150
161
  await secondWriter.commit('2/1');
151
162
 
163
+ const lifecycle = new ObjectStorageLifecycle(db, first.replicationStreamId, objectStorage);
164
+ const stoppedObject = `${lifecycle.definitionPrefix(stoppedBucketDefinitionId!)}stopped.bson`;
165
+ const similarDefinitionObject = `${lifecycle.definitionPrefix(`${stoppedBucketDefinitionId!}0`)}live.bson`;
166
+ for (const path of [stoppedObject, similarDefinitionObject]) {
167
+ await objectStorage.put(path, new Uint8Array(), {
168
+ contentType: 'application/bson',
169
+ contentEncoding: null
170
+ });
171
+ }
172
+
152
173
  const result = await cleanupStoppedSyncConfigs(
153
174
  (await factory.getActiveSyncConfig())!.storage as MongoSyncBucketStorageV3
154
175
  );
@@ -166,6 +187,8 @@ streams:
166
187
  expect(await collectionExists(db, parameterIndexCollection)).toBe(false);
167
188
  expect(await collectionExists(db, sceneRecordsCollection)).toBe(false);
168
189
  expect(await collectionExists(db, invitationRecordsCollection)).toBe(false);
190
+ expect(objectStorage.store.has(stoppedObject)).toBe(false);
191
+ expect(objectStorage.store.has(similarDefinitionObject)).toBe(true);
169
192
  expect(
170
193
  await db.sourceTables(first.replicationStreamId).countDocuments({ _id: sceneTable.id as bson.ObjectId })
171
194
  ).toBe(0);
@@ -0,0 +1,53 @@
1
+ import {
2
+ ObjectStorage,
3
+ ObjectStoragePutMetadata
4
+ } from '@module/storage/implementation/v3/object-storage/ObjectStorage.js';
5
+
6
+ export class MemoryObjectStorage implements ObjectStorage {
7
+ /**
8
+ * Public for testing purposes.
9
+ */
10
+ public readonly store = new Map<string, { data: Uint8Array; metadata: ObjectStoragePutMetadata }>();
11
+
12
+ async put(path: string, data: Uint8Array, metadata: ObjectStoragePutMetadata): Promise<void> {
13
+ this.store.set(path, { data, metadata: metadata });
14
+ }
15
+
16
+ async get(
17
+ path: string,
18
+ options?: { signal?: AbortSignal }
19
+ ): Promise<{ data: Uint8Array; metadata: ObjectStoragePutMetadata }> {
20
+ const signal = options?.signal;
21
+ signal?.throwIfAborted();
22
+ const data = this.store.get(path);
23
+ if (!data) {
24
+ throw new Error(`NotFound: ${path}`);
25
+ }
26
+ return data;
27
+ }
28
+
29
+ async *list(prefix: string, options?: { signal?: AbortSignal }): AsyncIterable<string> {
30
+ const signal = options?.signal;
31
+ for (const path of this.store.keys()) {
32
+ signal?.throwIfAborted();
33
+ if (path.startsWith(prefix)) {
34
+ yield path;
35
+ }
36
+ }
37
+ }
38
+
39
+ async delete(paths: string[]): Promise<void> {
40
+ for (const p of paths) {
41
+ this.store.delete(p);
42
+ }
43
+ }
44
+
45
+ async deletePrefix(prefix: string, options?: { signal?: AbortSignal }): Promise<{ objectCount: number }> {
46
+ const paths: string[] = [];
47
+ for await (const path of this.list(prefix, options)) {
48
+ paths.push(path);
49
+ }
50
+ await this.delete(paths);
51
+ return { objectCount: paths.length };
52
+ }
53
+ }