@rocicorp/zero 1.11.0-canary.13 → 1.11.0-canary.15

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 (252) hide show
  1. package/out/analyze-query/src/analyze-cli.js +2 -2
  2. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  3. package/out/ast-to-zql/src/ast-to-zql.d.ts +8 -1
  4. package/out/ast-to-zql/src/ast-to-zql.d.ts.map +1 -1
  5. package/out/ast-to-zql/src/ast-to-zql.js +25 -25
  6. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  7. package/out/otel/src/log-options.d.ts +16 -0
  8. package/out/otel/src/log-options.d.ts.map +1 -1
  9. package/out/otel/src/log-options.js +54 -1
  10. package/out/otel/src/log-options.js.map +1 -1
  11. package/out/replicache/src/get-kv-store-provider.d.ts +1 -1
  12. package/out/replicache/src/get-kv-store-provider.d.ts.map +1 -1
  13. package/out/replicache/src/get-kv-store-provider.js +4 -4
  14. package/out/replicache/src/get-kv-store-provider.js.map +1 -1
  15. package/out/replicache/src/kv/idb-store.d.ts +10 -1
  16. package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
  17. package/out/replicache/src/kv/idb-store.js +18 -2
  18. package/out/replicache/src/kv/idb-store.js.map +1 -1
  19. package/out/replicache/src/kv/mem-fallback-store.d.ts +54 -0
  20. package/out/replicache/src/kv/mem-fallback-store.d.ts.map +1 -0
  21. package/out/replicache/src/kv/mem-fallback-store.js +177 -0
  22. package/out/replicache/src/kv/mem-fallback-store.js.map +1 -0
  23. package/out/replicache/src/kv/op-sqlite/store.js +3 -3
  24. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  25. package/out/replicache/src/kv/sqlite-store.d.ts +9 -0
  26. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  27. package/out/replicache/src/kv/sqlite-store.js +86 -6
  28. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  29. package/out/replicache/src/new-client-channel.js.map +1 -1
  30. package/out/replicache/src/persist/collect-idb-databases.d.ts +17 -3
  31. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  32. package/out/replicache/src/persist/collect-idb-databases.js +81 -11
  33. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  34. package/out/replicache/src/persist/idb-databases-store-db-name.js +1 -1
  35. package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
  36. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  37. package/out/replicache/src/persist/persist.js +6 -3
  38. package/out/replicache/src/persist/persist.js.map +1 -1
  39. package/out/replicache/src/replicache-impl.d.ts +43 -3
  40. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  41. package/out/replicache/src/replicache-impl.js +135 -17
  42. package/out/replicache/src/replicache-impl.js.map +1 -1
  43. package/out/replicache/src/storage-failure.d.ts +37 -0
  44. package/out/replicache/src/storage-failure.d.ts.map +1 -0
  45. package/out/replicache/src/storage-failure.js +31 -0
  46. package/out/replicache/src/storage-failure.js.map +1 -0
  47. package/out/shared/src/random-values.js +12 -1
  48. package/out/shared/src/random-values.js.map +1 -1
  49. package/out/zero/package.js +1 -1
  50. package/out/zero/package.js.map +1 -1
  51. package/out/zero/src/zero.js +2 -1
  52. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  53. package/out/zero-cache/src/config/normalize.js +1 -1
  54. package/out/zero-cache/src/config/normalize.js.map +1 -1
  55. package/out/zero-cache/src/config/zero-config.d.ts +26 -0
  56. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  57. package/out/zero-cache/src/config/zero-config.js +36 -0
  58. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  59. package/out/zero-cache/src/observability/log-throttle.d.ts +44 -0
  60. package/out/zero-cache/src/observability/log-throttle.d.ts.map +1 -0
  61. package/out/zero-cache/src/observability/log-throttle.js +76 -0
  62. package/out/zero-cache/src/observability/log-throttle.js.map +1 -0
  63. package/out/zero-cache/src/scripts/permissions.d.ts +16 -0
  64. package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
  65. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
  66. package/out/zero-cache/src/server/runner/zero-dispatcher.js +2 -0
  67. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  68. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  69. package/out/zero-cache/src/server/syncer.js +20 -2
  70. package/out/zero-cache/src/server/syncer.js.map +1 -1
  71. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  72. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +27 -15
  73. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  74. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +1 -0
  75. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  76. package/out/zero-cache/src/services/change-source/common/replica-schema.js +15 -3
  77. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  78. package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
  79. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  80. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts +9 -0
  81. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -1
  82. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +204 -18
  83. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  84. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +11 -2
  85. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  86. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +11 -2
  87. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  88. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts +68 -0
  89. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.d.ts.map +1 -0
  90. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js +141 -0
  91. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js.map +1 -0
  92. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +43 -0
  93. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  94. package/out/zero-cache/src/services/change-source/protocol/current/data.js +10 -1
  95. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  96. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +57 -0
  97. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  98. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +20 -6
  99. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
  100. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +17 -7
  101. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  102. package/out/zero-cache/src/services/change-source/protocol/current.js +2 -1
  103. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts +66 -0
  104. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.d.ts.map +1 -0
  105. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js +154 -0
  106. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js.map +1 -0
  107. package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts +50 -0
  108. package/out/zero-cache/src/services/change-streamer/backfill-state.d.ts.map +1 -0
  109. package/out/zero-cache/src/services/change-streamer/backfill-state.js +268 -0
  110. package/out/zero-cache/src/services/change-streamer/backfill-state.js.map +1 -0
  111. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +7 -6
  112. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  113. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  114. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +20 -4
  115. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  116. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +26 -1
  117. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  118. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  119. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  120. package/out/zero-cache/src/services/change-streamer/storer.js +1 -1
  121. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  122. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts +88 -0
  123. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts.map +1 -1
  124. package/out/zero-cache/src/services/change-streamer/subscribe.js +9 -1
  125. package/out/zero-cache/src/services/change-streamer/subscribe.js.map +1 -1
  126. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +29 -0
  127. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  128. package/out/zero-cache/src/services/change-streamer/subscriber.js +34 -0
  129. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  130. package/out/zero-cache/src/services/plannerz.d.ts +159 -0
  131. package/out/zero-cache/src/services/plannerz.d.ts.map +1 -0
  132. package/out/zero-cache/src/services/plannerz.js +263 -0
  133. package/out/zero-cache/src/services/plannerz.js.map +1 -0
  134. package/out/zero-cache/src/services/replicator/change-log-cookies.js +1 -1
  135. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -1
  136. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  137. package/out/zero-cache/src/services/replicator/change-processor.js +44 -12
  138. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  139. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  140. package/out/zero-cache/src/services/replicator/incremental-sync.js +4 -3
  141. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  142. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +23 -2
  143. package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -1
  144. package/out/zero-cache/src/services/replicator/schema/backfilling.js +54 -2
  145. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -1
  146. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +11 -3
  147. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  148. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  149. package/out/zero-cache/src/services/replicator/write-worker.js +5 -1
  150. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  151. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts +81 -0
  152. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.d.ts.map +1 -0
  153. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js +128 -0
  154. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js.map +1 -0
  155. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +1 -1
  156. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +36 -1
  157. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  158. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +362 -20
  159. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  160. package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts +7 -0
  161. package/out/zero-cache/src/services/view-syncer/plan-warnings.d.ts.map +1 -0
  162. package/out/zero-cache/src/services/view-syncer/plan-warnings.js +35 -0
  163. package/out/zero-cache/src/services/view-syncer/plan-warnings.js.map +1 -0
  164. package/out/zero-cache/src/services/view-syncer/query-shape.d.ts +25 -0
  165. package/out/zero-cache/src/services/view-syncer/query-shape.d.ts.map +1 -0
  166. package/out/zero-cache/src/services/view-syncer/query-shape.js +28 -0
  167. package/out/zero-cache/src/services/view-syncer/query-shape.js.map +1 -0
  168. package/out/zero-cache/src/services/view-syncer/query-stats.d.ts +77 -0
  169. package/out/zero-cache/src/services/view-syncer/query-stats.d.ts.map +1 -0
  170. package/out/zero-cache/src/services/view-syncer/query-stats.js +206 -0
  171. package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -0
  172. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +11 -1
  173. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  174. package/out/zero-cache/src/services/view-syncer/snapshotter.js +7 -1
  175. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  176. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  177. package/out/zero-cache/src/services/view-syncer/view-syncer.js +49 -3
  178. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  179. package/out/zero-cache/src/workers/connection.js +3 -3
  180. package/out/zero-cache/src/workers/connection.js.map +1 -1
  181. package/out/zero-cache/src/workers/syncer.js +2 -2
  182. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  183. package/out/zero-client/src/client/options.d.ts +29 -0
  184. package/out/zero-client/src/client/options.d.ts.map +1 -1
  185. package/out/zero-client/src/client/options.js.map +1 -1
  186. package/out/zero-client/src/client/version.js +1 -1
  187. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  188. package/out/zero-client/src/client/zero.js +8 -23
  189. package/out/zero-client/src/client/zero.js.map +1 -1
  190. package/out/zero-client/src/mod.d.ts +1 -0
  191. package/out/zero-client/src/mod.d.ts.map +1 -1
  192. package/out/zero-client/src/mod.js +1 -0
  193. package/out/zero-protocol/src/down.d.ts +2 -2
  194. package/out/zero-react/src/zero.js +1 -0
  195. package/out/zero-solid/src/zero.js +1 -0
  196. package/out/zql/src/builder/builder.d.ts +6 -0
  197. package/out/zql/src/builder/builder.d.ts.map +1 -1
  198. package/out/zql/src/builder/builder.js +4 -3
  199. package/out/zql/src/builder/builder.js.map +1 -1
  200. package/out/zql/src/ivm/memory-source.d.ts +13 -0
  201. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  202. package/out/zql/src/ivm/memory-source.js +1 -1
  203. package/out/zql/src/ivm/memory-source.js.map +1 -1
  204. package/out/zql/src/planner/planner-builder.d.ts +12 -1
  205. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  206. package/out/zql/src/planner/planner-builder.js +8 -1
  207. package/out/zql/src/planner/planner-builder.js.map +1 -1
  208. package/out/zql/src/planner/planner-connection.d.ts +43 -0
  209. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  210. package/out/zql/src/planner/planner-connection.js +31 -4
  211. package/out/zql/src/planner/planner-connection.js.map +1 -1
  212. package/out/zql/src/planner/planner-graph.d.ts +10 -0
  213. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  214. package/out/zql/src/planner/planner-graph.js +14 -0
  215. package/out/zql/src/planner/planner-graph.js.map +1 -1
  216. package/out/zql/src/planner/planner-warnings.d.ts +83 -0
  217. package/out/zql/src/planner/planner-warnings.d.ts.map +1 -0
  218. package/out/zql/src/planner/planner-warnings.js +78 -0
  219. package/out/zql/src/planner/planner-warnings.js.map +1 -0
  220. package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
  221. package/out/zql/src/query/measure-push-operator.js +30 -8
  222. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  223. package/out/zqlite/src/pending-delta.d.ts +110 -0
  224. package/out/zqlite/src/pending-delta.d.ts.map +1 -0
  225. package/out/zqlite/src/pending-delta.js +278 -0
  226. package/out/zqlite/src/pending-delta.js.map +1 -0
  227. package/out/zqlite/src/query-delegate.d.ts.map +1 -1
  228. package/out/zqlite/src/query-delegate.js +5 -1
  229. package/out/zqlite/src/query-delegate.js.map +1 -1
  230. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  231. package/out/zqlite/src/sqlite-cost-model.js +52 -1
  232. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  233. package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
  234. package/out/zqlite/src/sqlite-stat-fanout.js +2 -26
  235. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  236. package/out/zqlite/src/sqlite-stat4-sample.d.ts +37 -0
  237. package/out/zqlite/src/sqlite-stat4-sample.d.ts.map +1 -0
  238. package/out/zqlite/src/sqlite-stat4-sample.js +61 -0
  239. package/out/zqlite/src/sqlite-stat4-sample.js.map +1 -0
  240. package/out/zqlite/src/table-source.d.ts +68 -0
  241. package/out/zqlite/src/table-source.d.ts.map +1 -1
  242. package/out/zqlite/src/table-source.js +206 -7
  243. package/out/zqlite/src/table-source.js.map +1 -1
  244. package/package.json +1 -1
  245. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +0 -35
  246. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +0 -1
  247. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +0 -83
  248. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +0 -1
  249. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts +0 -156
  250. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts.map +0 -1
  251. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js +0 -15
  252. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"new-client-channel.js","names":[],"sources":["../../../../replicache/src/new-client-channel.ts"],"sourcesContent":["import {BroadcastChannel} from '../../shared/src/broadcast-channel.ts';\nimport type {Read, Store} from './dag/store.ts';\nimport {getClientGroup} from './persist/client-groups.ts';\nimport {withRead} from './with-transactions.ts';\n\n// Older clients (<= replicache@13.0.1), listened on this channel name\n// and *asserted* that the messages received were an array containing exactly\n// one string.\nfunction makeChannelNameV0(replicacheName: string): string {\n return `replicache-new-client-group:${replicacheName}`;\n}\n\n// This channel name was introduced when we first needed to change the message\n// format. The design of the messages sent on this channel allows for\n// the message content to be extended in the future in a way that is\n// forward and backwards compatible. The message format can be extended\n// by adding new *optional* fields.\nfunction makeChannelNameV1(replicacheName: string): string {\n return `replicache-new-client-group-v1:${replicacheName}`;\n}\n\nexport {\n makeChannelNameV0 as makeChannelNameV0ForTesting,\n makeChannelNameV1 as makeChannelNameV1ForTesting,\n};\n\n// This message type can be extended with optional properties.\ntype NewClientChannelMessageV1 = {clientGroupID: string; idbName: string};\n\nfunction isNewClientChannelMessageV1(\n message: unknown,\n): message is NewClientChannelMessageV1 {\n return (\n typeof message === 'object' &&\n typeof (message as {clientGroupID: unknown}).clientGroupID === 'string' &&\n typeof (message as {idbName: unknown}).idbName === 'string'\n );\n}\n\nexport function initNewClientChannel(\n replicacheName: string,\n idbName: string,\n signal: AbortSignal,\n clientGroupID: string,\n isNewClientGroup: boolean,\n onUpdateNeeded: () => void,\n perdag: Store,\n) {\n if (signal.aborted) {\n return;\n }\n\n const channelV1 = new BroadcastChannel(makeChannelNameV1(replicacheName));\n if (isNewClientGroup) {\n channelV1.postMessage({clientGroupID, idbName});\n // Send expected format to V0 channel for old clients.\n const channelV0 = new BroadcastChannel(makeChannelNameV0(replicacheName));\n channelV0.postMessage([clientGroupID]);\n channelV0.close();\n }\n\n channelV1.onmessage = async (e: MessageEvent) => {\n const {data} = e;\n if (isNewClientChannelMessageV1(data)) {\n const {clientGroupID: newClientGroupID, idbName: newClientIDBName} = data;\n if (newClientGroupID !== clientGroupID) {\n if (newClientIDBName === idbName) {\n // Check if this client can see the new client's newClientGroupID in its\n // perdag. It should be able to if the clients share persistent\n // storage. However, with `ReplicacheOption.kvStore`\n // and `IDBStoreWithMemFallback` clients may not actually share\n // persistent storage. If storage is not shared, then there is no point\n // in updating, since clients cannot sync locally. If clients do update\n // in this case, they can continually cause each other to update, since\n // on each update the clients get assigned a new client group.\n const updateNeeded = await withRead(\n perdag,\n async (perdagRead: Read) =>\n (await getClientGroup(newClientGroupID, perdagRead)) !==\n undefined,\n );\n if (updateNeeded) {\n onUpdateNeeded();\n }\n } else {\n // Idb name is different, indicating new schema or format version.\n // Update to get assigned to newClientIDBName, and hopefully\n // newClientGroupID.\n // If storage is not actually shared (i.e. due to\n // `ReplicacheOption.kvStore`\n // or `IDBStoreWithMemFallback`) the new client will not\n // get assigned to newClientGroupID, but should get the\n // newClientIDBName.\n // Note: we don't try to read from newClientIDBName to see\n // if this client shares storage with the new client, because\n // the newClientIDBName may have a format version this client\n // cannot read.\n onUpdateNeeded();\n return;\n }\n }\n }\n };\n\n signal.addEventListener('abort', () => channelV1.close(), {once: true});\n}\n"],"mappings":";;;;AAQA,SAAS,kBAAkB,gBAAgC;CACzD,OAAO,+BAA+B;AACxC;AAOA,SAAS,kBAAkB,gBAAgC;CACzD,OAAO,kCAAkC;AAC3C;AAUA,SAAS,4BACP,SACsC;CACtC,OACE,OAAO,YAAY,YACnB,OAAQ,QAAqC,kBAAkB,YAC/D,OAAQ,QAA+B,YAAY;AAEvD;AAEA,SAAgB,qBACd,gBACA,SACA,QACA,eACA,kBACA,gBACA,QACA;CACA,IAAI,OAAO,SACT;CAGF,MAAM,YAAY,IAAI,GAAiB,kBAAkB,cAAc,CAAC;CACxE,IAAI,kBAAkB;EACpB,UAAU,YAAY;GAAC;GAAe;EAAO,CAAC;EAE9C,MAAM,YAAY,IAAI,GAAiB,kBAAkB,cAAc,CAAC;EACxE,UAAU,YAAY,CAAC,aAAa,CAAC;EACrC,UAAU,MAAM;CAClB;CAEA,UAAU,YAAY,OAAO,MAAoB;EAC/C,MAAM,EAAC,SAAQ;EACf,IAAI,4BAA4B,IAAI,GAAG;GACrC,MAAM,EAAC,eAAe,kBAAkB,SAAS,qBAAoB;GACrE,IAAI,qBAAqB,eACvB,IAAI,qBAAqB;QAenB,MANuB,SACzB,QACA,OAAO,eACJ,MAAM,eAAe,kBAAkB,UAAU,MAClD,KAAA,CACJ,GAEE,eAAe;GAAA,OAEZ;IAaL,eAAe;IACf;GACF;EAEJ;CACF;CAEA,OAAO,iBAAiB,eAAe,UAAU,MAAM,GAAG,EAAC,MAAM,KAAI,CAAC;AACxE"}
1
+ {"version":3,"file":"new-client-channel.js","names":[],"sources":["../../../../replicache/src/new-client-channel.ts"],"sourcesContent":["import {BroadcastChannel} from '../../shared/src/broadcast-channel.ts';\nimport type {Read, Store} from './dag/store.ts';\nimport {getClientGroup} from './persist/client-groups.ts';\nimport {withRead} from './with-transactions.ts';\n\n// Older clients (<= replicache@13.0.1), listened on this channel name\n// and *asserted* that the messages received were an array containing exactly\n// one string.\nfunction makeChannelNameV0(replicacheName: string): string {\n return `replicache-new-client-group:${replicacheName}`;\n}\n\n// This channel name was introduced when we first needed to change the message\n// format. The design of the messages sent on this channel allows for\n// the message content to be extended in the future in a way that is\n// forward and backwards compatible. The message format can be extended\n// by adding new *optional* fields.\nfunction makeChannelNameV1(replicacheName: string): string {\n return `replicache-new-client-group-v1:${replicacheName}`;\n}\n\nexport {\n makeChannelNameV0 as makeChannelNameV0ForTesting,\n makeChannelNameV1 as makeChannelNameV1ForTesting,\n};\n\n// This message type can be extended with optional properties.\ntype NewClientChannelMessageV1 = {clientGroupID: string; idbName: string};\n\nfunction isNewClientChannelMessageV1(\n message: unknown,\n): message is NewClientChannelMessageV1 {\n return (\n typeof message === 'object' &&\n typeof (message as {clientGroupID: unknown}).clientGroupID === 'string' &&\n typeof (message as {idbName: unknown}).idbName === 'string'\n );\n}\n\nexport function initNewClientChannel(\n replicacheName: string,\n idbName: string,\n signal: AbortSignal,\n clientGroupID: string,\n isNewClientGroup: boolean,\n onUpdateNeeded: () => void,\n perdag: Store,\n) {\n if (signal.aborted) {\n return;\n }\n\n const channelV1 = new BroadcastChannel(makeChannelNameV1(replicacheName));\n if (isNewClientGroup) {\n channelV1.postMessage({clientGroupID, idbName});\n // Send expected format to V0 channel for old clients.\n const channelV0 = new BroadcastChannel(makeChannelNameV0(replicacheName));\n channelV0.postMessage([clientGroupID]);\n channelV0.close();\n }\n\n channelV1.onmessage = async (e: MessageEvent) => {\n const {data} = e;\n if (isNewClientChannelMessageV1(data)) {\n const {clientGroupID: newClientGroupID, idbName: newClientIDBName} = data;\n if (newClientGroupID !== clientGroupID) {\n if (newClientIDBName === idbName) {\n // Check if this client can see the new client's newClientGroupID in its\n // perdag. It should be able to if the clients share persistent\n // storage. However, with `ReplicacheOption.kvStore`\n // or a store that failed to open (the instance then runs in memory)\n // clients may not actually share persistent storage. If storage is not shared, then there is no point\n // in updating, since clients cannot sync locally. If clients do update\n // in this case, they can continually cause each other to update, since\n // on each update the clients get assigned a new client group.\n const updateNeeded = await withRead(\n perdag,\n async (perdagRead: Read) =>\n (await getClientGroup(newClientGroupID, perdagRead)) !==\n undefined,\n );\n if (updateNeeded) {\n onUpdateNeeded();\n }\n } else {\n // Idb name is different, indicating new schema or format version.\n // Update to get assigned to newClientIDBName, and hopefully\n // newClientGroupID.\n // If storage is not actually shared (i.e. due to\n // `ReplicacheOption.kvStore`\n // or a store that failed to open) the new client will not\n // get assigned to newClientGroupID, but should get the\n // newClientIDBName.\n // Note: we don't try to read from newClientIDBName to see\n // if this client shares storage with the new client, because\n // the newClientIDBName may have a format version this client\n // cannot read.\n onUpdateNeeded();\n return;\n }\n }\n }\n };\n\n signal.addEventListener('abort', () => channelV1.close(), {once: true});\n}\n"],"mappings":";;;;AAQA,SAAS,kBAAkB,gBAAgC;CACzD,OAAO,+BAA+B;AACxC;AAOA,SAAS,kBAAkB,gBAAgC;CACzD,OAAO,kCAAkC;AAC3C;AAUA,SAAS,4BACP,SACsC;CACtC,OACE,OAAO,YAAY,YACnB,OAAQ,QAAqC,kBAAkB,YAC/D,OAAQ,QAA+B,YAAY;AAEvD;AAEA,SAAgB,qBACd,gBACA,SACA,QACA,eACA,kBACA,gBACA,QACA;CACA,IAAI,OAAO,SACT;CAGF,MAAM,YAAY,IAAI,GAAiB,kBAAkB,cAAc,CAAC;CACxE,IAAI,kBAAkB;EACpB,UAAU,YAAY;GAAC;GAAe;EAAO,CAAC;EAE9C,MAAM,YAAY,IAAI,GAAiB,kBAAkB,cAAc,CAAC;EACxE,UAAU,YAAY,CAAC,aAAa,CAAC;EACrC,UAAU,MAAM;CAClB;CAEA,UAAU,YAAY,OAAO,MAAoB;EAC/C,MAAM,EAAC,SAAQ;EACf,IAAI,4BAA4B,IAAI,GAAG;GACrC,MAAM,EAAC,eAAe,kBAAkB,SAAS,qBAAoB;GACrE,IAAI,qBAAqB,eACvB,IAAI,qBAAqB;QAenB,MANuB,SACzB,QACA,OAAO,eACJ,MAAM,eAAe,kBAAkB,UAAU,MAClD,KAAA,CACJ,GAEE,eAAe;GAAA,OAEZ;IAaL,eAAe;IACf;GACF;EAEJ;CACF;CAEA,OAAO,iBAAiB,eAAe,UAAU,MAAM,GAAG,EAAC,MAAM,KAAI,CAAC;AACxE"}
@@ -2,6 +2,7 @@ import type { LogContext, LogLevel, LogSink } from '@rocicorp/logger';
2
2
  import type { Store } from '../dag/store.ts';
3
3
  import type { CreateStore, DropStore, StoreProvider } from '../kv/store.ts';
4
4
  import type { OnClientsDeleted } from './clients.ts';
5
+ import type { IndexedDBDatabase } from './idb-databases-store.ts';
5
6
  import { IDBDatabasesStore } from './idb-databases-store.ts';
6
7
  /**
7
8
  * How frequently to try to collect
@@ -58,21 +59,34 @@ export type DropDatabaseOptions = {
58
59
  logSinks?: LogSink[] | undefined;
59
60
  };
60
61
  /**
61
- * Drops the specified database.
62
+ * Drops the specified database, from memory as well as from the configured
63
+ * store (see `onStorageFailure`). Rejects if the configured store cannot be
64
+ * opened or dropped.
62
65
  * @param dbName The name of the database to drop.
63
66
  * @param opts Options for dropping the database.
64
67
  */
65
68
  export declare function dropDatabase(dbName: string, opts?: DropDatabaseOptions): Promise<void>;
66
69
  /**
67
- * Deletes all IndexedDB data associated with Replicache.
70
+ * Deletes all IndexedDB data associated with Replicache, and the in-memory
71
+ * databases instances ran on after a storage failure (see
72
+ * `onStorageFailure`).
68
73
  *
69
74
  * Returns an object with the names of the successfully dropped databases
70
- * and any errors encountered while dropping.
75
+ * and any errors encountered while dropping. Rejects if the configured store
76
+ * cannot be opened.
71
77
  */
72
78
  export declare function dropAllDatabases(opts?: DropDatabaseOptions): Promise<{
73
79
  dropped: string[];
74
80
  errors: unknown[];
75
81
  }>;
82
+ /**
83
+ * Like {@link dropAllDatabases}, for the databases whose registry record
84
+ * matches `predicate`.
85
+ */
86
+ export declare function dropMatchingDatabases(predicate: (db: IndexedDBDatabase) => boolean, opts?: DropDatabaseOptions): Promise<{
87
+ dropped: string[];
88
+ errors: unknown[];
89
+ }>;
76
90
  /**
77
91
  * Deletes all IndexedDB data associated with Replicache.
78
92
  *
@@ -1 +1 @@
1
- {"version":3,"file":"collect-idb-databases.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAMpE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAY3C,OAAO,KAAK,EAAC,WAAW,EAAE,SAAS,EAAE,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAO1E,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAEvD,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,aAAa,EAC9B,eAAe,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC3B,MAAM,EAAE,MAAM,EACd,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,WAAgC,GAC5C,IAAI,CAyBN;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,iBAAiB,EAAE,iBAAiB,EACpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,aAAa,EAC9B,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,GAAE,WAAgC,GAC5C,OAAO,CAAC,IAAI,CAAC,CAyEf;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,iBAAiB,EACpC,WAAW,EAAE,SAAS,iBAIvB;AA6BD;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,KAAK,KAAK,CAAC;AA0C9E;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,aAAa,GAAG,SAAS,CAAC;IACpD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,iBAU5E;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC,CASD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,mBAAmB;aArBvD,MAAM,EAAE;YACT,OAAO,EAAE;GAsBlB"}
1
+ {"version":3,"file":"collect-idb-databases.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAMpE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAgB3C,OAAO,KAAK,EAAC,WAAW,EAAE,SAAS,EAAE,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAO1E,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAGnD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAEvD,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,aAAa,EAC9B,eAAe,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC3B,MAAM,EAAE,MAAM,EACd,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,WAAgC,GAC5C,IAAI,CAyBN;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,iBAAiB,EAAE,iBAAiB,EACpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,aAAa,EAC9B,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,GAAE,WAAgC,GAC5C,OAAO,CAAC,IAAI,CAAC,CAyEf;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,iBAAiB,EACpC,WAAW,EAAE,SAAS,iBAIvB;AA6BD;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,KAAK,KAAK,CAAC;AA0C9E;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,aAAa,GAAG,SAAS,CAAC;IACpD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,iBAe5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC;IACpE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC,CAED;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,CAAC,EAAE,EAAE,iBAAiB,KAAK,OAAO,EAC7C,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC,CAqBD;AA0CD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,mBAAmB;aAvFvD,MAAM,EAAE;YACT,OAAO,EAAE;GAwFlB"}
@@ -8,7 +8,9 @@ import { clientGroupHasPendingMutations, getClientGroups } from "./client-groups
8
8
  import { getClients } from "./clients.js";
9
9
  import { addDeletedClients, getDeletedClients, mergeDeletedClients, normalizeDeletedClients } from "../deleted-clients.js";
10
10
  import { getKVStoreProvider } from "../get-kv-store-provider.js";
11
+ import { fallbackStoreProvider, isFallbackStore } from "../kv/mem-fallback-store.js";
11
12
  import { createLogContext } from "../log-options.js";
13
+ import { getIDBDatabasesDBName } from "./idb-databases-store-db-name.js";
12
14
  import { IDBDatabasesStore } from "./idb-databases-store.js";
13
15
  //#region ../replicache/src/persist/collect-idb-databases.ts
14
16
  /**
@@ -93,25 +95,93 @@ function gatherDatabaseInfoForCollect(db, now, maxAge, enableMutationRecovery, k
93
95
  return canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, newDagStore(db.name, kvCreateStore), now, maxAge);
94
96
  }
95
97
  /**
96
- * Drops the specified database.
98
+ * Drops the specified database, from memory as well as from the configured
99
+ * store (see `onStorageFailure`). Rejects if the configured store cannot be
100
+ * opened or dropped.
97
101
  * @param dbName The name of the database to drop.
98
102
  * @param opts Options for dropping the database.
99
103
  */
100
104
  async function dropDatabase(dbName, opts) {
101
- const kvStoreProvider = getKVStoreProvider(createLogContext(opts?.logLevel, opts?.logSinks, { dropDatabase: void 0 }), opts?.kvStore);
102
- await dropDatabaseInternal(dbName, new IDBDatabasesStore(kvStoreProvider.create), kvStoreProvider.drop);
105
+ const logContext = createLogContext(opts?.logLevel, opts?.logSinks, { dropDatabase: void 0 });
106
+ for (const { provider, drops } of dropTargets(logContext, opts)) {
107
+ if (!drops(dbName)) continue;
108
+ const store = new IDBDatabasesStore(provider.create);
109
+ try {
110
+ await dropDatabaseInternal(dbName, store, provider.drop);
111
+ } finally {
112
+ await closeIgnoringErrors(store);
113
+ }
114
+ }
103
115
  }
104
116
  /**
105
- * Deletes all IndexedDB data associated with Replicache.
117
+ * Deletes all IndexedDB data associated with Replicache, and the in-memory
118
+ * databases instances ran on after a storage failure (see
119
+ * `onStorageFailure`).
106
120
  *
107
121
  * Returns an object with the names of the successfully dropped databases
108
- * and any errors encountered while dropping.
122
+ * and any errors encountered while dropping. Rejects if the configured store
123
+ * cannot be opened.
124
+ */
125
+ function dropAllDatabases(opts) {
126
+ return dropMatchingDatabases(() => true, opts);
127
+ }
128
+ /**
129
+ * Like {@link dropAllDatabases}, for the databases whose registry record
130
+ * matches `predicate`.
131
+ */
132
+ async function dropMatchingDatabases(predicate, opts) {
133
+ const logContext = createLogContext(opts?.logLevel, opts?.logSinks, { dropDatabases: void 0 });
134
+ const dropped = /* @__PURE__ */ new Set();
135
+ const errors = [];
136
+ for (const { provider, drops } of dropTargets(logContext, opts)) {
137
+ const store = new IDBDatabasesStore(provider.create);
138
+ try {
139
+ const databases = await store.getDatabases();
140
+ const result = await dropDatabases(store, Object.values(databases).filter((db) => predicate(db) && drops(db.name)).map((db) => db.name), provider.drop);
141
+ result.dropped.forEach((name) => dropped.add(name));
142
+ errors.push(...result.errors);
143
+ } finally {
144
+ await closeIgnoringErrors(store);
145
+ }
146
+ }
147
+ return {
148
+ dropped: [...dropped],
149
+ errors
150
+ };
151
+ }
152
+ /**
153
+ * The memory stores instances fell back to first, then the configured store.
154
+ * An instance whose store failed to open runs on memory stores of the same
155
+ * names (see `onStorageFailure`), and memory stores outlive the instance for
156
+ * the life of the process, so a drop clears them whatever the configured
157
+ * store is. Only those: the memory stores of `kvStore: 'mem'` instances are
158
+ * left alone unless `'mem'` is the store being dropped from. The configured
159
+ * store is still dropped, and its failure is reported: it may hold data on
160
+ * disk.
161
+ */
162
+ function dropTargets(lc, opts) {
163
+ const all = () => true;
164
+ if (opts?.kvStore === "mem") return [{
165
+ provider: getKVStoreProvider(lc, "mem"),
166
+ drops: all
167
+ }];
168
+ const targets = [];
169
+ if (isFallbackStore(getIDBDatabasesDBName())) targets.push({
170
+ provider: fallbackStoreProvider,
171
+ drops: isFallbackStore
172
+ });
173
+ targets.push({
174
+ provider: getKVStoreProvider(lc, opts?.kvStore),
175
+ drops: all
176
+ });
177
+ return targets;
178
+ }
179
+ /**
180
+ * A store that failed to open may also fail to close; the drop's own result
181
+ * is what the caller needs.
109
182
  */
110
- async function dropAllDatabases(opts) {
111
- const kvStoreProvider = getKVStoreProvider(createLogContext(opts?.logLevel, opts?.logSinks, { dropAllDatabases: void 0 }), opts?.kvStore);
112
- const store = new IDBDatabasesStore(kvStoreProvider.create);
113
- const databases = await store.getDatabases();
114
- return dropDatabases(store, Object.values(databases).map((db) => db.name), kvStoreProvider.drop);
183
+ function closeIgnoringErrors(store) {
184
+ return store.close().catch(() => void 0);
115
185
  }
116
186
  /**
117
187
  * If there are pending mutations in any of the clients in this db we return
@@ -135,6 +205,6 @@ function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, pe
135
205
  });
136
206
  }
137
207
  //#endregion
138
- export { COLLECT_IDB_INTERVAL, INITIAL_COLLECT_IDB_DELAY, dropAllDatabases, dropDatabase, dropDatabaseInternal, initCollectIDBDatabases };
208
+ export { COLLECT_IDB_INTERVAL, INITIAL_COLLECT_IDB_DELAY, dropAllDatabases, dropDatabase, dropDatabaseInternal, dropMatchingDatabases, initCollectIDBDatabases };
139
209
 
140
210
  //# sourceMappingURL=collect-idb-databases.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collect-idb-databases.js","names":[],"sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"sourcesContent":["import type {LogContext, LogLevel, LogSink} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport {InvalidRefCountError} from '../dag/invalid-ref-count-error.ts';\nimport {StoreImpl} from '../dag/store-impl.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n addDeletedClients,\n getDeletedClients,\n mergeDeletedClients,\n normalizeDeletedClients,\n type DeletedClients,\n type WritableDeletedClients,\n} from '../deleted-clients.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {getKVStoreProvider} from '../get-kv-store-provider.ts';\nimport {assertHash, newRandomHash} from '../hash.ts';\nimport type {CreateStore, DropStore, StoreProvider} from '../kv/store.ts';\nimport {createLogContext} from '../log-options.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n clientGroupHasPendingMutations,\n getClientGroups,\n} from './client-groups.ts';\nimport type {OnClientsDeleted} from './clients.ts';\nimport {getClients} from './clients.ts';\nimport type {IndexedDBDatabase} from './idb-databases-store.ts';\nimport {IDBDatabasesStore} from './idb-databases-store.ts';\n\n/**\n * How frequently to try to collect\n */\nexport const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours\n\n/**\n * We delay the initial collection to prevent doing it at startup.\n */\nexport const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1000; // 5 minutes\n\nexport function initCollectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n kvStoreProvider: StoreProvider,\n collectInterval: number,\n initialCollectDelay: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n lc: LogContext,\n signal: AbortSignal,\n newDagStore: NewDagStore = defaultNewDagStore,\n): void {\n let initial = true;\n initBgIntervalProcess(\n 'CollectIDBDatabases',\n async () => {\n await collectIDBDatabases(\n idbDatabasesStore,\n Date.now(),\n maxAge,\n kvStoreProvider,\n enableMutationRecovery,\n onClientsDeleted,\n newDagStore,\n );\n },\n () => {\n if (initial) {\n initial = false;\n return initialCollectDelay;\n }\n return collectInterval;\n },\n lc,\n signal,\n );\n}\n\n/**\n * Collects IDB databases that are no longer needed.\n */\nexport async function collectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n now: number,\n maxAge: number,\n kvStoreProvider: StoreProvider,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n newDagStore: NewDagStore = defaultNewDagStore,\n): Promise<void> {\n const databases = await idbDatabasesStore.getDatabases();\n\n const dbs = Object.values(databases);\n const collectResults = await Promise.all(\n dbs.map(\n async db =>\n [\n db.name,\n await gatherDatabaseInfoForCollect(\n db,\n now,\n maxAge,\n enableMutationRecovery,\n kvStoreProvider.create,\n newDagStore,\n ),\n ] as const,\n ),\n );\n\n const dbNamesToRemove: string[] = [];\n const dbNamesToKeep: string[] = [];\n const deletedClientsToRemove: WritableDeletedClients = [];\n for (const [dbName, [canCollect, deletedClients]] of collectResults) {\n if (canCollect) {\n dbNamesToRemove.push(dbName);\n deletedClientsToRemove.push(...deletedClients);\n } else {\n dbNamesToKeep.push(dbName);\n }\n }\n\n const {errors} = await dropDatabases(\n idbDatabasesStore,\n dbNamesToRemove,\n kvStoreProvider.drop,\n );\n if (errors.length) {\n throw errors[0];\n }\n\n if (deletedClientsToRemove.length > 0) {\n // Add the deleted clients to all the dbs that survived the collection.\n let newDeletedClients: DeletedClients = deletedClientsToRemove;\n for (const name of dbNamesToKeep) {\n let dbDeletedClients: DeletedClients;\n try {\n dbDeletedClients = await withWrite(\n newDagStore(name, kvStoreProvider.create),\n dagWrite => addDeletedClients(dagWrite, deletedClientsToRemove),\n );\n } catch (e) {\n if (!(e instanceof InvalidRefCountError)) {\n throw e;\n }\n // This database is corrupt. Its own instance will find out and\n // recover the next time it writes to it; here, just skip it and keep\n // collecting into the others, instead of letting one corrupt\n // database break every collection run forever.\n continue;\n }\n newDeletedClients = mergeDeletedClients(\n newDeletedClients,\n dbDeletedClients,\n );\n }\n // normalize and dedupe\n const normalizedDeletedClients = normalizeDeletedClients(newDeletedClients);\n\n // Call the callback with the normalized deleted clients\n await onClientsDeleted(normalizedDeletedClients);\n }\n}\n\nexport async function dropDatabaseInternal(\n name: string,\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n) {\n await kvDropStore(name);\n await idbDatabasesStore.deleteDatabases([name]);\n}\n\nasync function dropDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n namesToRemove: string[],\n kvDropStore: DropStore,\n): Promise<{dropped: string[]; errors: unknown[]}> {\n // Try to remove the databases in parallel. Don't let a single reject fail the\n // other ones. We will check for failures afterwards.\n const dropStoreResults = await Promise.allSettled(\n namesToRemove.map(async name => {\n await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);\n return name;\n }),\n );\n\n const dropped: string[] = [];\n const errors: unknown[] = [];\n for (const result of dropStoreResults) {\n if (result.status === 'fulfilled') {\n dropped.push(result.value);\n } else {\n errors.push(result.reason);\n }\n }\n\n return {dropped, errors};\n}\n\n/**\n * Creates the dag store used to inspect and update a database during\n * collection. Callers can override it to install store hooks, for example so\n * a corrupt ref count found while writing deleted clients is recovered from.\n */\nexport type NewDagStore = (name: string, kvCreateStore: CreateStore) => Store;\n\nfunction defaultNewDagStore(name: string, kvCreateStore: CreateStore): Store {\n const perKvStore = kvCreateStore(name);\n return new StoreImpl(perKvStore, newRandomHash, assertHash);\n}\n\n/**\n * If any client has a recent heartbeat or there are pending mutations we\n * return `[false]`. Otherwise we return `[true, deletedClients]`.\n */\nfunction gatherDatabaseInfoForCollect(\n db: IndexedDBDatabase,\n now: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n kvCreateStore: CreateStore,\n newDagStore: NewDagStore,\n): MaybePromise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n if (db.replicacheFormatVersion > FormatVersion.Latest) {\n return [false];\n }\n\n // If increase the format version we need to decide how to deal with this\n // logic.\n assert(\n db.replicacheFormatVersion === FormatVersion.DD31 ||\n db.replicacheFormatVersion === FormatVersion.V6 ||\n db.replicacheFormatVersion === FormatVersion.V7,\n () =>\n `Expected replicacheFormatVersion to be DD31, V6, or V7, got ${db.replicacheFormatVersion}`,\n );\n return canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery,\n newDagStore(db.name, kvCreateStore),\n now,\n maxAge,\n );\n}\n\n/**\n * Options for `dropDatabase` and `dropAllDatabases`.\n */\nexport type DropDatabaseOptions = {\n /**\n * Allows providing a custom implementation of the underlying storage layer.\n * Default is `'idb'`.\n */\n kvStore?: 'idb' | 'mem' | StoreProvider | undefined;\n /**\n * Determines how much logging to do. When this is set to `'debug'`,\n * Replicache will also log `'info'` and `'error'` messages. When set to\n * `'info'` we log `'info'` and `'error'` but not `'debug'`. When set to\n * `'error'` we only log `'error'` messages.\n * Default is `'info'`.\n */\n logLevel?: LogLevel | undefined;\n /**\n * Enables custom handling of logs.\n *\n * By default logs are logged to the console. If you would like logs to be\n * sent elsewhere (e.g. to a cloud logging service like DataDog) you can\n * provide an array of {@link LogSink}s. Logs at or above\n * {@link DropDatabaseOptions.logLevel} are sent to each of these {@link LogSink}s.\n * If you would still like logs to go to the console, include\n * `consoleLogSink` in the array.\n *\n * ```ts\n * logSinks: [consoleLogSink, myCloudLogSink],\n * ```\n * Default is `[consoleLogSink]`.\n */\n logSinks?: LogSink[] | undefined;\n};\n\n/**\n * Drops the specified database.\n * @param dbName The name of the database to drop.\n * @param opts Options for dropping the database.\n */\nexport async function dropDatabase(dbName: string, opts?: DropDatabaseOptions) {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropDatabase: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n await dropDatabaseInternal(\n dbName,\n new IDBDatabasesStore(kvStoreProvider.create),\n kvStoreProvider.drop,\n );\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n */\nexport async function dropAllDatabases(opts?: DropDatabaseOptions): Promise<{\n dropped: string[];\n errors: unknown[];\n}> {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropAllDatabases: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n const store = new IDBDatabasesStore(kvStoreProvider.create);\n const databases = await store.getDatabases();\n const dbNames = Object.values(databases).map(db => db.name);\n return dropDatabases(store, dbNames, kvStoreProvider.drop);\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n *\n * @deprecated Use `dropAllDatabases` instead.\n */\nexport function deleteAllReplicacheData(opts?: DropDatabaseOptions) {\n return dropAllDatabases(opts);\n}\n\n/**\n * If there are pending mutations in any of the clients in this db we return\n * `[false]`. If any client has a recent heartbeat we also return `[false]`.\n * Otherwise we return `[true, deletedClients]`.\n */\nfunction canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery: boolean,\n perdag: Store,\n now: number,\n maxAge: number,\n): Promise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n return withRead(perdag, async read => {\n // If mutation recovery is disabled we do not care if there are pending\n // mutations when we decide if we can collect the database.\n if (enableMutationRecovery) {\n const clientGroups = await getClientGroups(read);\n for (const clientGroup of clientGroups.values()) {\n if (clientGroupHasPendingMutations(clientGroup)) {\n return [false];\n }\n }\n }\n\n const clients = await getClients(read);\n\n // Don't collect if any client has a recent heartbeat (is still active).\n // This is defense in depth - normally lastOpenedTimestampMS is kept fresh\n // by the heartbeat, but this check protects against edge cases.\n for (const [, client] of clients) {\n if (now - client.heartbeatTimestampMs < maxAge) {\n return [false];\n }\n }\n\n const existingDeletedClients = await getDeletedClients(read);\n const deletedClients: WritableDeletedClients = [...existingDeletedClients];\n\n // Add all current clients to the deleted clients list\n for (const [clientID, client] of clients) {\n deletedClients.push({\n clientID,\n clientGroupID: client.clientGroupID,\n });\n }\n\n // The normalization (deduping and sorting) will be done when storing\n return [true, deletedClients];\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"collect-idb-databases.js","names":[],"sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"sourcesContent":["import type {LogContext, LogLevel, LogSink} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport {InvalidRefCountError} from '../dag/invalid-ref-count-error.ts';\nimport {StoreImpl} from '../dag/store-impl.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n addDeletedClients,\n getDeletedClients,\n mergeDeletedClients,\n normalizeDeletedClients,\n type DeletedClients,\n type WritableDeletedClients,\n} from '../deleted-clients.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {getKVStoreProvider} from '../get-kv-store-provider.ts';\nimport {assertHash, newRandomHash} from '../hash.ts';\nimport {\n fallbackStoreProvider,\n isFallbackStore,\n} from '../kv/mem-fallback-store.ts';\nimport type {CreateStore, DropStore, StoreProvider} from '../kv/store.ts';\nimport {createLogContext} from '../log-options.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n clientGroupHasPendingMutations,\n getClientGroups,\n} from './client-groups.ts';\nimport type {OnClientsDeleted} from './clients.ts';\nimport {getClients} from './clients.ts';\nimport {getIDBDatabasesDBName} from './idb-databases-store-db-name.ts';\nimport type {IndexedDBDatabase} from './idb-databases-store.ts';\nimport {IDBDatabasesStore} from './idb-databases-store.ts';\n\n/**\n * How frequently to try to collect\n */\nexport const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours\n\n/**\n * We delay the initial collection to prevent doing it at startup.\n */\nexport const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1000; // 5 minutes\n\nexport function initCollectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n kvStoreProvider: StoreProvider,\n collectInterval: number,\n initialCollectDelay: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n lc: LogContext,\n signal: AbortSignal,\n newDagStore: NewDagStore = defaultNewDagStore,\n): void {\n let initial = true;\n initBgIntervalProcess(\n 'CollectIDBDatabases',\n async () => {\n await collectIDBDatabases(\n idbDatabasesStore,\n Date.now(),\n maxAge,\n kvStoreProvider,\n enableMutationRecovery,\n onClientsDeleted,\n newDagStore,\n );\n },\n () => {\n if (initial) {\n initial = false;\n return initialCollectDelay;\n }\n return collectInterval;\n },\n lc,\n signal,\n );\n}\n\n/**\n * Collects IDB databases that are no longer needed.\n */\nexport async function collectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n now: number,\n maxAge: number,\n kvStoreProvider: StoreProvider,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n newDagStore: NewDagStore = defaultNewDagStore,\n): Promise<void> {\n const databases = await idbDatabasesStore.getDatabases();\n\n const dbs = Object.values(databases);\n const collectResults = await Promise.all(\n dbs.map(\n async db =>\n [\n db.name,\n await gatherDatabaseInfoForCollect(\n db,\n now,\n maxAge,\n enableMutationRecovery,\n kvStoreProvider.create,\n newDagStore,\n ),\n ] as const,\n ),\n );\n\n const dbNamesToRemove: string[] = [];\n const dbNamesToKeep: string[] = [];\n const deletedClientsToRemove: WritableDeletedClients = [];\n for (const [dbName, [canCollect, deletedClients]] of collectResults) {\n if (canCollect) {\n dbNamesToRemove.push(dbName);\n deletedClientsToRemove.push(...deletedClients);\n } else {\n dbNamesToKeep.push(dbName);\n }\n }\n\n const {errors} = await dropDatabases(\n idbDatabasesStore,\n dbNamesToRemove,\n kvStoreProvider.drop,\n );\n if (errors.length) {\n throw errors[0];\n }\n\n if (deletedClientsToRemove.length > 0) {\n // Add the deleted clients to all the dbs that survived the collection.\n let newDeletedClients: DeletedClients = deletedClientsToRemove;\n for (const name of dbNamesToKeep) {\n let dbDeletedClients: DeletedClients;\n try {\n dbDeletedClients = await withWrite(\n newDagStore(name, kvStoreProvider.create),\n dagWrite => addDeletedClients(dagWrite, deletedClientsToRemove),\n );\n } catch (e) {\n if (!(e instanceof InvalidRefCountError)) {\n throw e;\n }\n // This database is corrupt. Its own instance will find out and\n // recover the next time it writes to it; here, just skip it and keep\n // collecting into the others, instead of letting one corrupt\n // database break every collection run forever.\n continue;\n }\n newDeletedClients = mergeDeletedClients(\n newDeletedClients,\n dbDeletedClients,\n );\n }\n // normalize and dedupe\n const normalizedDeletedClients = normalizeDeletedClients(newDeletedClients);\n\n // Call the callback with the normalized deleted clients\n await onClientsDeleted(normalizedDeletedClients);\n }\n}\n\nexport async function dropDatabaseInternal(\n name: string,\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n) {\n await kvDropStore(name);\n await idbDatabasesStore.deleteDatabases([name]);\n}\n\nasync function dropDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n namesToRemove: string[],\n kvDropStore: DropStore,\n): Promise<{dropped: string[]; errors: unknown[]}> {\n // Try to remove the databases in parallel. Don't let a single reject fail the\n // other ones. We will check for failures afterwards.\n const dropStoreResults = await Promise.allSettled(\n namesToRemove.map(async name => {\n await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);\n return name;\n }),\n );\n\n const dropped: string[] = [];\n const errors: unknown[] = [];\n for (const result of dropStoreResults) {\n if (result.status === 'fulfilled') {\n dropped.push(result.value);\n } else {\n errors.push(result.reason);\n }\n }\n\n return {dropped, errors};\n}\n\n/**\n * Creates the dag store used to inspect and update a database during\n * collection. Callers can override it to install store hooks, for example so\n * a corrupt ref count found while writing deleted clients is recovered from.\n */\nexport type NewDagStore = (name: string, kvCreateStore: CreateStore) => Store;\n\nfunction defaultNewDagStore(name: string, kvCreateStore: CreateStore): Store {\n const perKvStore = kvCreateStore(name);\n return new StoreImpl(perKvStore, newRandomHash, assertHash);\n}\n\n/**\n * If any client has a recent heartbeat or there are pending mutations we\n * return `[false]`. Otherwise we return `[true, deletedClients]`.\n */\nfunction gatherDatabaseInfoForCollect(\n db: IndexedDBDatabase,\n now: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n kvCreateStore: CreateStore,\n newDagStore: NewDagStore,\n): MaybePromise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n if (db.replicacheFormatVersion > FormatVersion.Latest) {\n return [false];\n }\n\n // If increase the format version we need to decide how to deal with this\n // logic.\n assert(\n db.replicacheFormatVersion === FormatVersion.DD31 ||\n db.replicacheFormatVersion === FormatVersion.V6 ||\n db.replicacheFormatVersion === FormatVersion.V7,\n () =>\n `Expected replicacheFormatVersion to be DD31, V6, or V7, got ${db.replicacheFormatVersion}`,\n );\n return canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery,\n newDagStore(db.name, kvCreateStore),\n now,\n maxAge,\n );\n}\n\n/**\n * Options for `dropDatabase` and `dropAllDatabases`.\n */\nexport type DropDatabaseOptions = {\n /**\n * Allows providing a custom implementation of the underlying storage layer.\n * Default is `'idb'`.\n */\n kvStore?: 'idb' | 'mem' | StoreProvider | undefined;\n /**\n * Determines how much logging to do. When this is set to `'debug'`,\n * Replicache will also log `'info'` and `'error'` messages. When set to\n * `'info'` we log `'info'` and `'error'` but not `'debug'`. When set to\n * `'error'` we only log `'error'` messages.\n * Default is `'info'`.\n */\n logLevel?: LogLevel | undefined;\n /**\n * Enables custom handling of logs.\n *\n * By default logs are logged to the console. If you would like logs to be\n * sent elsewhere (e.g. to a cloud logging service like DataDog) you can\n * provide an array of {@link LogSink}s. Logs at or above\n * {@link DropDatabaseOptions.logLevel} are sent to each of these {@link LogSink}s.\n * If you would still like logs to go to the console, include\n * `consoleLogSink` in the array.\n *\n * ```ts\n * logSinks: [consoleLogSink, myCloudLogSink],\n * ```\n * Default is `[consoleLogSink]`.\n */\n logSinks?: LogSink[] | undefined;\n};\n\n/**\n * Drops the specified database, from memory as well as from the configured\n * store (see `onStorageFailure`). Rejects if the configured store cannot be\n * opened or dropped.\n * @param dbName The name of the database to drop.\n * @param opts Options for dropping the database.\n */\nexport async function dropDatabase(dbName: string, opts?: DropDatabaseOptions) {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropDatabase: undefined,\n });\n for (const {provider, drops} of dropTargets(logContext, opts)) {\n if (!drops(dbName)) {\n continue;\n }\n const store = new IDBDatabasesStore(provider.create);\n try {\n await dropDatabaseInternal(dbName, store, provider.drop);\n } finally {\n await closeIgnoringErrors(store);\n }\n }\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache, and the in-memory\n * databases instances ran on after a storage failure (see\n * `onStorageFailure`).\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping. Rejects if the configured store\n * cannot be opened.\n */\nexport function dropAllDatabases(opts?: DropDatabaseOptions): Promise<{\n dropped: string[];\n errors: unknown[];\n}> {\n return dropMatchingDatabases(() => true, opts);\n}\n\n/**\n * Like {@link dropAllDatabases}, for the databases whose registry record\n * matches `predicate`.\n */\nexport async function dropMatchingDatabases(\n predicate: (db: IndexedDBDatabase) => boolean,\n opts?: DropDatabaseOptions,\n): Promise<{\n dropped: string[];\n errors: unknown[];\n}> {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropDatabases: undefined,\n });\n const dropped = new Set<string>();\n const errors: unknown[] = [];\n for (const {provider, drops} of dropTargets(logContext, opts)) {\n const store = new IDBDatabasesStore(provider.create);\n try {\n const databases = await store.getDatabases();\n const dbNames = Object.values(databases)\n .filter(db => predicate(db) && drops(db.name))\n .map(db => db.name);\n const result = await dropDatabases(store, dbNames, provider.drop);\n result.dropped.forEach(name => dropped.add(name));\n errors.push(...result.errors);\n } finally {\n await closeIgnoringErrors(store);\n }\n }\n return {dropped: [...dropped], errors};\n}\n\ntype DropTarget = {\n provider: StoreProvider;\n /** Whether a database of this name is dropped from `provider`. */\n drops: (name: string) => boolean;\n};\n\n/**\n * The memory stores instances fell back to first, then the configured store.\n * An instance whose store failed to open runs on memory stores of the same\n * names (see `onStorageFailure`), and memory stores outlive the instance for\n * the life of the process, so a drop clears them whatever the configured\n * store is. Only those: the memory stores of `kvStore: 'mem'` instances are\n * left alone unless `'mem'` is the store being dropped from. The configured\n * store is still dropped, and its failure is reported: it may hold data on\n * disk.\n */\nfunction dropTargets(\n lc: LogContext,\n opts: DropDatabaseOptions | undefined,\n): DropTarget[] {\n const all = () => true;\n if (opts?.kvStore === 'mem') {\n return [{provider: getKVStoreProvider(lc, 'mem'), drops: all}];\n }\n const targets: DropTarget[] = [];\n if (isFallbackStore(getIDBDatabasesDBName())) {\n targets.push({provider: fallbackStoreProvider, drops: isFallbackStore});\n }\n targets.push({provider: getKVStoreProvider(lc, opts?.kvStore), drops: all});\n return targets;\n}\n\n/**\n * A store that failed to open may also fail to close; the drop's own result\n * is what the caller needs.\n */\nfunction closeIgnoringErrors(store: IDBDatabasesStore): Promise<void> {\n return store.close().catch(() => undefined);\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n *\n * @deprecated Use `dropAllDatabases` instead.\n */\nexport function deleteAllReplicacheData(opts?: DropDatabaseOptions) {\n return dropAllDatabases(opts);\n}\n\n/**\n * If there are pending mutations in any of the clients in this db we return\n * `[false]`. If any client has a recent heartbeat we also return `[false]`.\n * Otherwise we return `[true, deletedClients]`.\n */\nfunction canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery: boolean,\n perdag: Store,\n now: number,\n maxAge: number,\n): Promise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n return withRead(perdag, async read => {\n // If mutation recovery is disabled we do not care if there are pending\n // mutations when we decide if we can collect the database.\n if (enableMutationRecovery) {\n const clientGroups = await getClientGroups(read);\n for (const clientGroup of clientGroups.values()) {\n if (clientGroupHasPendingMutations(clientGroup)) {\n return [false];\n }\n }\n }\n\n const clients = await getClients(read);\n\n // Don't collect if any client has a recent heartbeat (is still active).\n // This is defense in depth - normally lastOpenedTimestampMS is kept fresh\n // by the heartbeat, but this check protects against edge cases.\n for (const [, client] of clients) {\n if (now - client.heartbeatTimestampMs < maxAge) {\n return [false];\n }\n }\n\n const existingDeletedClients = await getDeletedClients(read);\n const deletedClients: WritableDeletedClients = [...existingDeletedClients];\n\n // Add all current clients to the deleted clients list\n for (const [clientID, client] of clients) {\n deletedClients.push({\n clientID,\n clientGroupID: client.clientGroupID,\n });\n }\n\n // The normalization (deduping and sorting) will be done when storing\n return [true, deletedClients];\n });\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import "../kv/idb-store-with-mem-fallback.js";
1
+ import "../kv/idb-store.js";
2
2
  //#region ../replicache/src/persist/idb-databases-store-db-name.ts
3
3
  var IDB_DATABASES_DB_NAME = "replicache-dbs-v0";
4
4
  var testNamespace = "";
@@ -1 +1 @@
1
- {"version":3,"file":"idb-databases-store-db-name.js","names":[],"sources":["../../../../../replicache/src/persist/idb-databases-store-db-name.ts"],"sourcesContent":["import {randomUint64} from '../../../shared/src/random-uint64.ts';\nimport {dropIDBStoreWithMemFallback} from '../kv/idb-store-with-mem-fallback.ts';\n\nconst IDB_DATABASES_VERSION = 0;\nconst IDB_DATABASES_DB_NAME = 'replicache-dbs-v' + IDB_DATABASES_VERSION;\n\nlet testNamespace = '';\n\n/** Namespace db name in test to isolate tests' indexeddb state. */\nexport function setupForTest(): void {\n testNamespace = randomUint64().toString(36);\n}\n\nexport function teardownForTest(): Promise<void> {\n const idbDatabasesDBName = getIDBDatabasesDBName();\n testNamespace = '';\n return dropIDBStoreWithMemFallback(idbDatabasesDBName);\n}\n\nexport function getIDBDatabasesDBName(): string {\n return testNamespace + IDB_DATABASES_DB_NAME;\n}\n"],"mappings":";;AAIA,IAAM,wBAAwB;AAE9B,IAAI,gBAAgB;AAapB,SAAgB,wBAAgC;CAC9C,OAAO,gBAAgB;AACzB"}
1
+ {"version":3,"file":"idb-databases-store-db-name.js","names":[],"sources":["../../../../../replicache/src/persist/idb-databases-store-db-name.ts"],"sourcesContent":["import {randomUint64} from '../../../shared/src/random-uint64.ts';\nimport {dropIDBStore} from '../kv/idb-store.ts';\n\nconst IDB_DATABASES_VERSION = 0;\nconst IDB_DATABASES_DB_NAME = 'replicache-dbs-v' + IDB_DATABASES_VERSION;\n\nlet testNamespace = '';\n\n/** Namespace db name in test to isolate tests' indexeddb state. */\nexport function setupForTest(): void {\n testNamespace = randomUint64().toString(36);\n}\n\nexport function teardownForTest(): Promise<void> {\n const idbDatabasesDBName = getIDBDatabasesDBName();\n testNamespace = '';\n return dropIDBStore(idbDatabasesDBName);\n}\n\nexport function getIDBDatabasesDBName(): string {\n return testNamespace + IDB_DATABASES_DB_NAME;\n}\n"],"mappings":";;AAIA,IAAM,wBAAwB;AAE9B,IAAI,gBAAgB;AAapB,SAAgB,wBAAgC;CAC9C,OAAO,gBAAgB;AACzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/persist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAO,KAAK,EAAQ,MAAM,iBAAiB,CAAC;AAexD,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAEhE,OAAO,KAAK,EAAC,UAAU,EAAa,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAgB,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAgB7C,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,OAAO,EACrB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,EAChD,4BAA4B,sBAA0B,GACrD,OAAO,CAAC,IAAI,CAAC,CAmMf"}
1
+ {"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/persist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAO,KAAK,EAAQ,MAAM,iBAAiB,CAAC;AAexD,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAEhE,OAAO,KAAK,EAAC,UAAU,EAAa,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAgB,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAgB7C,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,OAAO,EACrB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,EAChD,4BAA4B,sBAA0B,GACrD,OAAO,CAAC,IAAI,CAAC,CAwNf"}
@@ -42,28 +42,31 @@ async function persistDD31(lc, clientID, memdag, perdag, mutators, closed, forma
42
42
  ];
43
43
  });
44
44
  if (closed()) return;
45
- const [newMemdagMutations, memdagBaseSnapshot, gatheredChunks] = await withRead(memdag, async (memdagRead) => {
45
+ const [newMemdagMutations, memdagBaseSnapshot, gatheredChunks, zeroDataForBaseSnapshot] = await withRead(memdag, async (memdagRead) => {
46
46
  const memdagHeadCommit = await commitFromHead(DEFAULT_HEAD_NAME, memdagRead);
47
47
  const newMutations = await localMutationsGreaterThan(memdagHeadCommit, { [clientID]: perdagLMID || 0 }, memdagRead);
48
48
  const memdagBaseSnapshot = await baseSnapshotFromCommit(memdagHeadCommit, memdagRead);
49
49
  assertSnapshotCommitDD31(memdagBaseSnapshot);
50
50
  let gatheredChunks;
51
+ let zeroData;
51
52
  if (compareCookiesForSnapshots(memdagBaseSnapshot, perdagBaseSnapshot) > 0) {
52
53
  await onGatherMemOnlyChunksForTest();
53
54
  const memdagBaseSnapshotHash = memdagBaseSnapshot.chunk.hash;
54
55
  const visitor = new GatherMemoryOnlyVisitor(memdagRead);
55
56
  await visitor.visit(memdagBaseSnapshotHash);
56
57
  gatheredChunks = visitor.gatheredChunks;
58
+ zeroData = getZeroData && await getZeroData(memdagBaseSnapshotHash, { openLazyRead: memdagRead });
57
59
  }
58
60
  return [
59
61
  newMutations,
60
62
  memdagBaseSnapshot,
61
- gatheredChunks
63
+ gatheredChunks,
64
+ zeroData
62
65
  ];
63
66
  });
64
67
  if (closed()) return;
65
68
  let memdagBaseSnapshotPersisted = false;
66
- let zeroDataForRebase = getZeroData && await getZeroData(memdagBaseSnapshot.chunk.hash);
69
+ let zeroDataForRebase = zeroDataForBaseSnapshot;
67
70
  await withWrite(perdag, async (perdagWrite) => {
68
71
  const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] = await getClientGroupInfo(perdagWrite, mainClientGroupID);
69
72
  let newMainClientGroupHeadHash = latestPerdagMainClientGroupHeadCommit.chunk.hash;
@@ -1 +1 @@
1
- {"version":3,"file":"persist.js","names":[],"sources":["../../../../../replicache/src/persist/persist.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {getOrInsert, getOrInsertComputed} from '../../../shared/src/map.ts';\nimport type {Chunk} from '../dag/chunk.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Read, Store, Write} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n type Meta,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsDD31,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption, ZeroTxData} from '../replicache-options.ts';\nimport type {ClientGroupID, ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n type ClientGroup,\n getClientGroup,\n setClientGroup,\n} from './client-groups.ts';\nimport {\n assertClientV6,\n assertHasClientState,\n getClientGroupIDForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {GatherMemoryOnlyVisitor} from './gather-mem-only-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * Persists the client's memdag state to the client's perdag client group.\n *\n * Persists the base snapshot from memdag to the client's perdag client group,\n * but only if it’s newer than the client's perdag client group’s base snapshot.\n * The base snapshot is persisted by gathering all memory-only chunks in the dag\n * subgraph rooted at the base snapshot's commit and writing them to the perdag.\n * Once the base snapshot is persisted, rebases onto this new base snapshot all\n * local commits from the client's perdag client group that are not already\n * reflected in the base snapshot.\n *\n * Whether or not the base snapshot is persisted, rebases onto the client's\n * perdag client group all memdag local commits not already in the client's\n * perdag client group's history.\n *\n * Also updates the `lastMutationIDs` and `lastServerAckdMutationIDs` properties\n * of the client's client group's entry in the `ClientGroupMap`.\n */\nexport async function persistDD31(\n lc: LogContext,\n clientID: ClientID,\n memdag: LazyStore,\n perdag: Store,\n mutators: MutatorDefs,\n closed: () => boolean,\n formatVersion: FormatVersion,\n getZeroData: ZeroOption['getTxData'] | undefined,\n onGatherMemOnlyChunksForTest = () => Promise.resolve(),\n): Promise<void> {\n if (closed()) {\n return;\n }\n\n const [perdagLMID, perdagBaseSnapshot, mainClientGroupID] = await withRead(\n perdag,\n async perdagRead => {\n await assertHasClientState(clientID, perdagRead);\n const mainClientGroupID = await getClientGroupIDForClient(\n clientID,\n perdagRead,\n );\n assert(\n mainClientGroupID,\n `No main client group for clientID: ${clientID}`,\n );\n const [, perdagMainClientGroupHeadCommit] = await getClientGroupInfo(\n perdagRead,\n mainClientGroupID,\n );\n const perdagLMID = await perdagMainClientGroupHeadCommit.getMutationID(\n clientID,\n perdagRead,\n );\n const perdagBaseSnapshot = await baseSnapshotFromCommit(\n perdagMainClientGroupHeadCommit,\n perdagRead,\n );\n assertSnapshotCommitDD31(perdagBaseSnapshot);\n return [perdagLMID, perdagBaseSnapshot, mainClientGroupID];\n },\n );\n\n if (closed()) {\n return;\n }\n const [newMemdagMutations, memdagBaseSnapshot, gatheredChunks] =\n await withRead(memdag, async memdagRead => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagRead,\n );\n const newMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLMID || 0},\n memdagRead,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagRead,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n let gatheredChunks: ReadonlyMap<Hash, Chunk> | undefined;\n if (\n compareCookiesForSnapshots(memdagBaseSnapshot, perdagBaseSnapshot) > 0\n ) {\n await onGatherMemOnlyChunksForTest();\n // Might need to persist snapshot, we will have to double check\n // after gathering the snapshot chunks from memdag\n const memdagBaseSnapshotHash = memdagBaseSnapshot.chunk.hash;\n // Gather all memory only chunks from base snapshot on the memdag.\n const visitor = new GatherMemoryOnlyVisitor(memdagRead);\n await visitor.visit(memdagBaseSnapshotHash);\n gatheredChunks = visitor.gatheredChunks;\n }\n\n return [newMutations, memdagBaseSnapshot, gatheredChunks];\n });\n\n if (closed()) {\n return;\n }\n\n let memdagBaseSnapshotPersisted = false;\n // Carried across both rebase batches below: each batch continues from the\n // branch the previous one ended on.\n let zeroDataForRebase =\n getZeroData && (await getZeroData(memdagBaseSnapshot.chunk.hash));\n\n await withWrite(perdag, async perdagWrite => {\n const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] =\n await getClientGroupInfo(perdagWrite, mainClientGroupID);\n\n // These initial values for newMainClientGroupHeadHash, mutationIDs,\n // lastServerAckdMutationIDs are correct for the case where the memdag\n // snapshot is *not* persisted. If the memdag snapshot is persisted\n // these values are overwritten appropriately.\n let newMainClientGroupHeadHash: Hash =\n latestPerdagMainClientGroupHeadCommit.chunk.hash;\n let mutationIDs: Record<ClientID, number> = {\n ...mainClientGroup.mutationIDs,\n };\n let {lastServerAckdMutationIDs} = mainClientGroup;\n\n if (gatheredChunks) {\n // check if memdag snapshot still newer than perdag snapshot\n\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n\n const latestPerdagBaseSnapshot = await baseSnapshotFromCommit(\n latestPerdagMainClientGroupHeadCommit,\n perdagWrite,\n );\n assertSnapshotCommitDD31(latestPerdagBaseSnapshot);\n\n // check if memdag snapshot still newer than perdag snapshot\n if (\n compareCookiesForSnapshots(\n memdagBaseSnapshot,\n latestPerdagBaseSnapshot,\n ) > 0\n ) {\n // still newer, persist memdag snapshot by writing chunks\n memdagBaseSnapshotPersisted = true;\n await Promise.all(\n Array.from(gatheredChunks.values(), c => perdagWrite.putChunk(c)),\n );\n\n await setClient(\n clientID,\n {\n ...client,\n persistHash: memdagBaseSnapshot.chunk.hash,\n },\n perdagWrite,\n );\n // Rebase local mutations from perdag main client group onto new\n // snapshot\n newMainClientGroupHeadHash = memdagBaseSnapshot.chunk.hash;\n const mainClientGroupLocalMutations = await localMutationsDD31(\n mainClientGroup.headHash,\n perdagWrite,\n );\n\n lastServerAckdMutationIDs = memdagBaseSnapshot.meta.lastMutationIDs;\n mutationIDs = {...lastServerAckdMutationIDs};\n\n const rebased = await rebase(\n mainClientGroupLocalMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForRebase,\n );\n newMainClientGroupHeadHash = rebased.hash;\n // The mutations rebased below run after these, so they have to see\n // what these wrote.\n zeroDataForRebase = rebased.zeroData;\n }\n }\n\n let zeroDataForPerdagHeadCommit: ZeroTxData | undefined;\n if (!memdagBaseSnapshotPersisted) {\n zeroDataForPerdagHeadCommit =\n getZeroData &&\n (await getZeroData(newMainClientGroupHeadHash, {\n openLazySourceRead: perdagWrite,\n }));\n }\n\n // rebase new memdag mutations onto perdag\n newMainClientGroupHeadHash = (\n await rebase(\n newMemdagMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForPerdagHeadCommit ?? zeroDataForRebase,\n )\n ).hash;\n\n const newMainClientGroup = {\n ...mainClientGroup,\n headHash: newMainClientGroupHeadHash,\n mutationIDs,\n lastServerAckdMutationIDs,\n };\n\n await setClientGroup(mainClientGroupID, newMainClientGroup, perdagWrite);\n });\n\n if (gatheredChunks && memdagBaseSnapshotPersisted) {\n await withWrite(memdag, memdagWrite =>\n memdagWrite.chunksPersisted([...gatheredChunks.keys()]),\n );\n }\n}\n\nasync function getClientGroupInfo(\n perdagRead: Read,\n clientGroupID: ClientGroupID,\n): Promise<[ClientGroup, Commit<Meta>]> {\n const clientGroup = await getClientGroup(clientGroupID, perdagRead);\n assert(clientGroup, `No client group for clientGroupID: ${clientGroupID}`);\n return [clientGroup, await commitFromHash(clientGroup.headHash, perdagRead)];\n}\n\ntype RebasedBatch = {\n hash: Hash;\n zeroData: ZeroTxData | undefined;\n};\n\nasync function rebase(\n mutations: Commit<LocalMetaDD31>[],\n basis: Hash,\n write: Write,\n mutators: MutatorDefs,\n mutationIDs: Record<ClientID, number>,\n lc: LogContext,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<RebasedBatch> {\n const basisMutationIDs = new Map<Hash, Map<ClientID, Promise<number>>>();\n const getBasisMutationID = (\n basisHash: Hash,\n clientID: ClientID,\n ): Promise<number> =>\n getOrInsertComputed(\n getOrInsert(basisMutationIDs, basisHash, new Map()),\n clientID,\n () =>\n commitFromHash(basisHash, write).then(commit =>\n commit.getMutationID(clientID, write),\n ),\n );\n for (let i = mutations.length - 1; i >= 0; i--) {\n const mutationCommit = mutations[i];\n const {meta} = mutationCommit;\n if (meta.mutationID > (await getBasisMutationID(basis, meta.clientID))) {\n mutationIDs[meta.clientID] = meta.mutationID;\n const {result, zeroData: next} = await rebaseMutationAndPutCommit(\n mutationCommit,\n write,\n basis,\n mutators,\n lc,\n meta.clientID,\n formatVersion,\n zeroData,\n );\n basis = result.chunk.hash;\n zeroData = next;\n }\n }\n return {hash: basis, zeroData};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"persist.js","names":[],"sources":["../../../../../replicache/src/persist/persist.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {getOrInsert, getOrInsertComputed} from '../../../shared/src/map.ts';\nimport type {Chunk} from '../dag/chunk.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Read, Store, Write} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n type Meta,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsDD31,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption, ZeroTxData} from '../replicache-options.ts';\nimport type {ClientGroupID, ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n type ClientGroup,\n getClientGroup,\n setClientGroup,\n} from './client-groups.ts';\nimport {\n assertClientV6,\n assertHasClientState,\n getClientGroupIDForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {GatherMemoryOnlyVisitor} from './gather-mem-only-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * Persists the client's memdag state to the client's perdag client group.\n *\n * Persists the base snapshot from memdag to the client's perdag client group,\n * but only if it’s newer than the client's perdag client group’s base snapshot.\n * The base snapshot is persisted by gathering all memory-only chunks in the dag\n * subgraph rooted at the base snapshot's commit and writing them to the perdag.\n * Once the base snapshot is persisted, rebases onto this new base snapshot all\n * local commits from the client's perdag client group that are not already\n * reflected in the base snapshot.\n *\n * Whether or not the base snapshot is persisted, rebases onto the client's\n * perdag client group all memdag local commits not already in the client's\n * perdag client group's history.\n *\n * Also updates the `lastMutationIDs` and `lastServerAckdMutationIDs` properties\n * of the client's client group's entry in the `ClientGroupMap`.\n */\nexport async function persistDD31(\n lc: LogContext,\n clientID: ClientID,\n memdag: LazyStore,\n perdag: Store,\n mutators: MutatorDefs,\n closed: () => boolean,\n formatVersion: FormatVersion,\n getZeroData: ZeroOption['getTxData'] | undefined,\n onGatherMemOnlyChunksForTest = () => Promise.resolve(),\n): Promise<void> {\n if (closed()) {\n return;\n }\n\n const [perdagLMID, perdagBaseSnapshot, mainClientGroupID] = await withRead(\n perdag,\n async perdagRead => {\n await assertHasClientState(clientID, perdagRead);\n const mainClientGroupID = await getClientGroupIDForClient(\n clientID,\n perdagRead,\n );\n assert(\n mainClientGroupID,\n `No main client group for clientID: ${clientID}`,\n );\n const [, perdagMainClientGroupHeadCommit] = await getClientGroupInfo(\n perdagRead,\n mainClientGroupID,\n );\n const perdagLMID = await perdagMainClientGroupHeadCommit.getMutationID(\n clientID,\n perdagRead,\n );\n const perdagBaseSnapshot = await baseSnapshotFromCommit(\n perdagMainClientGroupHeadCommit,\n perdagRead,\n );\n assertSnapshotCommitDD31(perdagBaseSnapshot);\n return [perdagLMID, perdagBaseSnapshot, mainClientGroupID];\n },\n );\n\n if (closed()) {\n return;\n }\n const [\n newMemdagMutations,\n memdagBaseSnapshot,\n gatheredChunks,\n zeroDataForBaseSnapshot,\n ] = await withRead(memdag, async memdagRead => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagRead,\n );\n const newMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLMID || 0},\n memdagRead,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagRead,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n let gatheredChunks: ReadonlyMap<Hash, Chunk> | undefined;\n let zeroData: ZeroTxData | undefined;\n if (\n compareCookiesForSnapshots(memdagBaseSnapshot, perdagBaseSnapshot) > 0\n ) {\n await onGatherMemOnlyChunksForTest();\n // Might need to persist snapshot, we will have to double check\n // after gathering the snapshot chunks from memdag\n const memdagBaseSnapshotHash = memdagBaseSnapshot.chunk.hash;\n // Gather all memory only chunks from base snapshot on the memdag.\n const visitor = new GatherMemoryOnlyVisitor(memdagRead);\n await visitor.visit(memdagBaseSnapshotHash);\n gatheredChunks = visitor.gatheredChunks;\n\n // Fork Zero's IVM state to the base snapshot while this read is still\n // held. The fork is a diff from the IVM's current head (the memdag main\n // head) to the base snapshot, and both are memdag chunks that a\n // concurrent poke is free to collect the moment this read is released:\n // moving the main head drops the superseded local commits, and a\n // snapshot commit carries no ref to its basis. Taking the fork under\n // the same lock that fixed `memdagBaseSnapshot` is what keeps the\n // diff's endpoints alive; taken afterwards it raced every poke, and\n // lost as `ChunkNotFoundError` out of persist. It is only needed when\n // the snapshot may be persisted; otherwise the perdag rebase below\n // forks to the perdag head instead.\n zeroData =\n getZeroData &&\n (await getZeroData(memdagBaseSnapshotHash, {\n openLazyRead: memdagRead,\n }));\n }\n\n return [newMutations, memdagBaseSnapshot, gatheredChunks, zeroData];\n });\n\n if (closed()) {\n return;\n }\n\n let memdagBaseSnapshotPersisted = false;\n // Carried across both rebase batches below: each batch continues from the\n // branch the previous one ended on.\n let zeroDataForRebase = zeroDataForBaseSnapshot;\n\n await withWrite(perdag, async perdagWrite => {\n const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] =\n await getClientGroupInfo(perdagWrite, mainClientGroupID);\n\n // These initial values for newMainClientGroupHeadHash, mutationIDs,\n // lastServerAckdMutationIDs are correct for the case where the memdag\n // snapshot is *not* persisted. If the memdag snapshot is persisted\n // these values are overwritten appropriately.\n let newMainClientGroupHeadHash: Hash =\n latestPerdagMainClientGroupHeadCommit.chunk.hash;\n let mutationIDs: Record<ClientID, number> = {\n ...mainClientGroup.mutationIDs,\n };\n let {lastServerAckdMutationIDs} = mainClientGroup;\n\n if (gatheredChunks) {\n // check if memdag snapshot still newer than perdag snapshot\n\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n\n const latestPerdagBaseSnapshot = await baseSnapshotFromCommit(\n latestPerdagMainClientGroupHeadCommit,\n perdagWrite,\n );\n assertSnapshotCommitDD31(latestPerdagBaseSnapshot);\n\n // check if memdag snapshot still newer than perdag snapshot\n if (\n compareCookiesForSnapshots(\n memdagBaseSnapshot,\n latestPerdagBaseSnapshot,\n ) > 0\n ) {\n // still newer, persist memdag snapshot by writing chunks\n memdagBaseSnapshotPersisted = true;\n await Promise.all(\n Array.from(gatheredChunks.values(), c => perdagWrite.putChunk(c)),\n );\n\n await setClient(\n clientID,\n {\n ...client,\n persistHash: memdagBaseSnapshot.chunk.hash,\n },\n perdagWrite,\n );\n // Rebase local mutations from perdag main client group onto new\n // snapshot\n newMainClientGroupHeadHash = memdagBaseSnapshot.chunk.hash;\n const mainClientGroupLocalMutations = await localMutationsDD31(\n mainClientGroup.headHash,\n perdagWrite,\n );\n\n lastServerAckdMutationIDs = memdagBaseSnapshot.meta.lastMutationIDs;\n mutationIDs = {...lastServerAckdMutationIDs};\n\n const rebased = await rebase(\n mainClientGroupLocalMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForRebase,\n );\n newMainClientGroupHeadHash = rebased.hash;\n // The mutations rebased below run after these, so they have to see\n // what these wrote.\n zeroDataForRebase = rebased.zeroData;\n }\n }\n\n let zeroDataForPerdagHeadCommit: ZeroTxData | undefined;\n if (!memdagBaseSnapshotPersisted) {\n zeroDataForPerdagHeadCommit =\n getZeroData &&\n (await getZeroData(newMainClientGroupHeadHash, {\n openLazySourceRead: perdagWrite,\n }));\n }\n\n // rebase new memdag mutations onto perdag\n newMainClientGroupHeadHash = (\n await rebase(\n newMemdagMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForPerdagHeadCommit ?? zeroDataForRebase,\n )\n ).hash;\n\n const newMainClientGroup = {\n ...mainClientGroup,\n headHash: newMainClientGroupHeadHash,\n mutationIDs,\n lastServerAckdMutationIDs,\n };\n\n await setClientGroup(mainClientGroupID, newMainClientGroup, perdagWrite);\n });\n\n if (gatheredChunks && memdagBaseSnapshotPersisted) {\n await withWrite(memdag, memdagWrite =>\n memdagWrite.chunksPersisted([...gatheredChunks.keys()]),\n );\n }\n}\n\nasync function getClientGroupInfo(\n perdagRead: Read,\n clientGroupID: ClientGroupID,\n): Promise<[ClientGroup, Commit<Meta>]> {\n const clientGroup = await getClientGroup(clientGroupID, perdagRead);\n assert(clientGroup, `No client group for clientGroupID: ${clientGroupID}`);\n return [clientGroup, await commitFromHash(clientGroup.headHash, perdagRead)];\n}\n\ntype RebasedBatch = {\n hash: Hash;\n zeroData: ZeroTxData | undefined;\n};\n\nasync function rebase(\n mutations: Commit<LocalMetaDD31>[],\n basis: Hash,\n write: Write,\n mutators: MutatorDefs,\n mutationIDs: Record<ClientID, number>,\n lc: LogContext,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<RebasedBatch> {\n const basisMutationIDs = new Map<Hash, Map<ClientID, Promise<number>>>();\n const getBasisMutationID = (\n basisHash: Hash,\n clientID: ClientID,\n ): Promise<number> =>\n getOrInsertComputed(\n getOrInsert(basisMutationIDs, basisHash, new Map()),\n clientID,\n () =>\n commitFromHash(basisHash, write).then(commit =>\n commit.getMutationID(clientID, write),\n ),\n );\n for (let i = mutations.length - 1; i >= 0; i--) {\n const mutationCommit = mutations[i];\n const {meta} = mutationCommit;\n if (meta.mutationID > (await getBasisMutationID(basis, meta.clientID))) {\n mutationIDs[meta.clientID] = meta.mutationID;\n const {result, zeroData: next} = await rebaseMutationAndPutCommit(\n mutationCommit,\n write,\n basis,\n mutators,\n lc,\n meta.clientID,\n formatVersion,\n zeroData,\n );\n basis = result.chunk.hash;\n zeroData = next;\n }\n }\n return {hash: basis, zeroData};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,eAAsB,YACpB,IACA,UACA,QACA,QACA,UACA,QACA,eACA,aACA,qCAAqC,QAAQ,QAAQ,GACtC;CACf,IAAI,OAAO,GACT;CAGF,MAAM,CAAC,YAAY,oBAAoB,qBAAqB,MAAM,SAChE,QACA,OAAM,eAAc;EAClB,MAAM,qBAAqB,UAAU,UAAU;EAC/C,MAAM,oBAAoB,MAAM,0BAC9B,UACA,UACF;EACA,OACE,mBACA,sCAAsC,UACxC;EACA,MAAM,GAAG,mCAAmC,MAAM,mBAChD,YACA,iBACF;EACA,MAAM,aAAa,MAAM,gCAAgC,cACvD,UACA,UACF;EACA,MAAM,qBAAqB,MAAM,uBAC/B,iCACA,UACF;EACA,yBAAyB,kBAAkB;EAC3C,OAAO;GAAC;GAAY;GAAoB;EAAiB;CAC3D,CACF;CAEA,IAAI,OAAO,GACT;CAEF,MAAM,CACJ,oBACA,oBACA,gBACA,2BACE,MAAM,SAAS,QAAQ,OAAM,eAAc;EAC7C,MAAM,mBAAmB,MAAM,eAC7B,mBACA,UACF;EACA,MAAM,eAAe,MAAM,0BACzB,kBACA,GAAE,WAAW,cAAc,EAAC,GAC5B,UACF;EACA,MAAM,qBAAqB,MAAM,uBAC/B,kBACA,UACF;EACA,yBAAyB,kBAAkB;EAE3C,IAAI;EACJ,IAAI;EACJ,IACE,2BAA2B,oBAAoB,kBAAkB,IAAI,GACrE;GACA,MAAM,6BAA6B;GAGnC,MAAM,yBAAyB,mBAAmB,MAAM;GAExD,MAAM,UAAU,IAAI,wBAAwB,UAAU;GACtD,MAAM,QAAQ,MAAM,sBAAsB;GAC1C,iBAAiB,QAAQ;GAazB,WACE,eACC,MAAM,YAAY,wBAAwB,EACzC,cAAc,WAChB,CAAC;EACL;EAEA,OAAO;GAAC;GAAc;GAAoB;GAAgB;EAAQ;CACpE,CAAC;CAED,IAAI,OAAO,GACT;CAGF,IAAI,8BAA8B;CAGlC,IAAI,oBAAoB;CAExB,MAAM,UAAU,QAAQ,OAAM,gBAAe;EAC3C,MAAM,CAAC,iBAAiB,yCACtB,MAAM,mBAAmB,aAAa,iBAAiB;EAMzD,IAAI,6BACF,sCAAsC,MAAM;EAC9C,IAAI,cAAwC,EAC1C,GAAG,gBAAgB,YACrB;EACA,IAAI,EAAC,8BAA6B;EAElC,IAAI,gBAAgB;GAGlB,MAAM,SAAS,MAAM,cAAc,UAAU,WAAW;GACxD,eAAe,MAAM;GAErB,MAAM,2BAA2B,MAAM,uBACrC,uCACA,WACF;GACA,yBAAyB,wBAAwB;GAGjD,IACE,2BACE,oBACA,wBACF,IAAI,GACJ;IAEA,8BAA8B;IAC9B,MAAM,QAAQ,IACZ,MAAM,KAAK,eAAe,OAAO,IAAG,MAAK,YAAY,SAAS,CAAC,CAAC,CAClE;IAEA,MAAM,UACJ,UACA;KACE,GAAG;KACH,aAAa,mBAAmB,MAAM;IACxC,GACA,WACF;IAGA,6BAA6B,mBAAmB,MAAM;IACtD,MAAM,gCAAgC,MAAM,mBAC1C,gBAAgB,UAChB,WACF;IAEA,4BAA4B,mBAAmB,KAAK;IACpD,cAAc,EAAC,GAAG,0BAAyB;IAE3C,MAAM,UAAU,MAAM,OACpB,+BACA,4BACA,aACA,UACA,aACA,IACA,eACA,iBACF;IACA,6BAA6B,QAAQ;IAGrC,oBAAoB,QAAQ;GAC9B;EACF;EAEA,IAAI;EACJ,IAAI,CAAC,6BACH,8BACE,eACC,MAAM,YAAY,4BAA4B,EAC7C,oBAAoB,YACtB,CAAC;EAIL,8BACE,MAAM,OACJ,oBACA,4BACA,aACA,UACA,aACA,IACA,eACA,+BAA+B,iBACjC,GACA;EASF,MAAM,eAAe,mBAAmB;GANtC,GAAG;GACH,UAAU;GACV;GACA;EAGsC,GAAoB,WAAW;CACzE,CAAC;CAED,IAAI,kBAAkB,6BACpB,MAAM,UAAU,SAAQ,gBACtB,YAAY,gBAAgB,CAAC,GAAG,eAAe,KAAK,CAAC,CAAC,CACxD;AAEJ;AAEA,eAAe,mBACb,YACA,eACsC;CACtC,MAAM,cAAc,MAAM,eAAe,eAAe,UAAU;CAClE,OAAO,aAAa,sCAAsC,eAAe;CACzE,OAAO,CAAC,aAAa,MAAM,eAAe,YAAY,UAAU,UAAU,CAAC;AAC7E;AAOA,eAAe,OACb,WACA,OACA,OACA,UACA,aACA,IACA,eACA,UACuB;CACvB,MAAM,mCAAmB,IAAI,IAA0C;CACvE,MAAM,sBACJ,WACA,aAEA,oBACE,YAAY,kBAAkB,2BAAW,IAAI,IAAI,CAAC,GAClD,gBAEE,eAAe,WAAW,KAAK,EAAE,MAAK,WACpC,OAAO,cAAc,UAAU,KAAK,CACtC,CACJ;CACF,KAAK,IAAI,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KAAK;EAC9C,MAAM,iBAAiB,UAAU;EACjC,MAAM,EAAC,SAAQ;EACf,IAAI,KAAK,aAAc,MAAM,mBAAmB,OAAO,KAAK,QAAQ,GAAI;GACtE,YAAY,KAAK,YAAY,KAAK;GAClC,MAAM,EAAC,QAAQ,UAAU,SAAQ,MAAM,2BACrC,gBACA,OACA,OACA,UACA,IACA,KAAK,UACL,eACA,QACF;GACA,QAAQ,OAAO,MAAM;GACrB,WAAW;EACb;CACF;CACA,OAAO;EAAC,MAAM;EAAO;CAAQ;AAC/B"}
@@ -10,6 +10,7 @@ import { type OnClientsDeleted } from './persist/clients.ts';
10
10
  import type { Puller } from './puller.ts';
11
11
  import { type Pusher } from './pusher.ts';
12
12
  import type { ReplicacheOptions, ZeroOption } from './replicache-options.ts';
13
+ import { type StorageFailureError } from './storage-failure.ts';
13
14
  import { type SubscribeOptions, type SubscriptionsManager, type WatchCallbackForOptions, type WatchNoIndexCallback, type WatchOptions } from './subscriptions.ts';
14
15
  import type { ReadTransaction } from './transactions.ts';
15
16
  import type { BeginPullResult, MakeMutators, MutatorDefs, PokeInternal, QueryInternal, RequestOptions, UpdateNeededReason } from './types.ts';
@@ -79,9 +80,9 @@ export declare class ReplicacheImpl<MD extends MutatorDefs = {}> {
79
80
  */
80
81
  get idbName(): string;
81
82
  /**
82
- * The KV store backing this instance. Its `kind` reflects the storage
83
- * currently in use, e.g. `'mem'` after an IndexedDB store fell back to
84
- * memory.
83
+ * The KV store backing this instance. It is a memory store once a storage
84
+ * failure while opening moved the instance onto memory (see
85
+ * `onStorageFailure`).
85
86
  */
86
87
  get kvStore(): KVStore;
87
88
  set auth(auth: string);
@@ -148,6 +149,45 @@ export declare class ReplicacheImpl<MD extends MutatorDefs = {}> {
148
149
  * reloading automatically.
149
150
  */
150
151
  onClientStateNotFound: (() => void) | null;
152
+ /**
153
+ * `onStorageFailure` is called once, the first time the local kv store
154
+ * reports that its storage has failed rather than its data, by throwing a
155
+ * {@link StorageFailureError}: the device is out of space (`full`), the
156
+ * database cannot be opened (`cannot-open`), or a read or write to it failed
157
+ * (`io-error`). The SQLite stores and the IndexedDB store report these; a
158
+ * custom `StoreProvider` can throw a `StorageFailureError` itself.
159
+ *
160
+ * A failure while the instance is opening moves it onto memory for the
161
+ * session, where it runs as with `kvStore: 'mem'`: it persists and
162
+ * refreshes against the memory stores, and nothing reaches the disk.
163
+ *
164
+ * A failure after that stops persisting and refreshing: a rebuild would
165
+ * open the same failing storage, and a wipe would destroy an intact replica
166
+ * for a fault that is not in the data. Queries and mutations keep running
167
+ * against what the in-memory dag holds, and mutations keep pushing to the
168
+ * server, but nothing is persisted locally until the app creates a new
169
+ * instance. A read that needs a chunk the in-memory dag has not loaded from
170
+ * the store yet, or has since evicted from its cache, still goes to the
171
+ * store and fails the way any store read does; that failure reaches its
172
+ * caller and is not reclassified here. An invalid ref count reported while
173
+ * the store is failing with `cannot-open` or `io-error` is NOT treated as
174
+ * corruption (the database is not dropped and {@link onClientStateNotFound}
175
+ * is not called), because a store that cannot complete a read or write is
176
+ * what produces such readings. A `full` disk keeps the drop: a torn write
177
+ * there is real corruption, and deleting the database is also what frees
178
+ * the space.
179
+ *
180
+ * After the open, the failure is detected when a transaction on the store
181
+ * fails to begin or to commit, whichever caller ran it (`persist()`, the
182
+ * heartbeat, garbage collection, ...), and when `persist()` or `refresh()`
183
+ * fails. The background maintenance processes (heartbeat, client and
184
+ * client-group GC, database collection, mutation recovery) stop on it
185
+ * instead of retrying against the store at their interval.
186
+ *
187
+ * There is no default behavior other than logging. An app that shows a
188
+ * "free up space" or "restart" screen can do so from here.
189
+ */
190
+ onStorageFailure: ((failure: StorageFailureError) => void) | null;
151
191
  /**
152
192
  * `onUpdateNeeded` is called when a code update is needed.
153
193
  *
@@ -1 +1 @@
1
- {"version":3,"file":"replicache-impl.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-impl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replicache-impl.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-impl.ts"],"names":[],"mappings":"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"}