@rocicorp/zero 1.11.4 → 1.11.5

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 (192) hide show
  1. package/out/replicache/src/sync/request-id.js +2 -2
  2. package/out/replicache/src/sync/request-id.js.map +1 -1
  3. package/out/shared/src/bigint-json.d.ts.map +1 -1
  4. package/out/shared/src/bigint-json.js +1 -0
  5. package/out/shared/src/bigint-json.js.map +1 -1
  6. package/out/shared/src/headers.d.ts +12 -0
  7. package/out/shared/src/headers.d.ts.map +1 -0
  8. package/out/shared/src/headers.js +20 -0
  9. package/out/shared/src/headers.js.map +1 -0
  10. package/out/shared/src/random-uint64.d.ts.map +1 -1
  11. package/out/shared/src/random-uint64.js +2 -2
  12. package/out/shared/src/random-uint64.js.map +1 -1
  13. package/out/shared/src/random-values.d.ts +14 -1
  14. package/out/shared/src/random-values.d.ts.map +1 -1
  15. package/out/shared/src/random-values.js +24 -4
  16. package/out/shared/src/random-values.js.map +1 -1
  17. package/out/zero/package.js +1 -1
  18. package/out/zero/package.js.map +1 -1
  19. package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
  20. package/out/zero-cache/src/auth/auth.js +5 -0
  21. package/out/zero-cache/src/auth/auth.js.map +1 -1
  22. package/out/zero-cache/src/config/zero-config.d.ts +21 -0
  23. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  24. package/out/zero-cache/src/config/zero-config.js +47 -9
  25. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  26. package/out/zero-cache/src/custom-queries/transform-query.js +2 -2
  27. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  28. package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
  29. package/out/zero-cache/src/db/pg-to-lite.js +3 -2
  30. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  31. package/out/zero-cache/src/db/pg-type-parser.d.ts +13 -0
  32. package/out/zero-cache/src/db/pg-type-parser.d.ts.map +1 -1
  33. package/out/zero-cache/src/db/pg-type-parser.js +55 -2
  34. package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
  35. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  36. package/out/zero-cache/src/server/change-streamer.js +5 -2
  37. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  38. package/out/zero-cache/src/server/inspector-delegate.d.ts +2 -25
  39. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  40. package/out/zero-cache/src/server/inspector-delegate.js +6 -29
  41. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  42. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  43. package/out/zero-cache/src/server/main.js +5 -0
  44. package/out/zero-cache/src/server/main.js.map +1 -1
  45. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  46. package/out/zero-cache/src/server/replicator.js +3 -2
  47. package/out/zero-cache/src/server/replicator.js.map +1 -1
  48. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  49. package/out/zero-cache/src/server/syncer.js +5 -4
  50. package/out/zero-cache/src/server/syncer.js.map +1 -1
  51. package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
  52. package/out/zero-cache/src/server/worker-dispatcher.js +2 -1
  53. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  54. package/out/zero-cache/src/services/admin-auth.d.ts +22 -0
  55. package/out/zero-cache/src/services/admin-auth.d.ts.map +1 -0
  56. package/out/zero-cache/src/services/admin-auth.js +42 -0
  57. package/out/zero-cache/src/services/admin-auth.js.map +1 -0
  58. package/out/zero-cache/src/services/auth-attempt-counter.d.ts +33 -0
  59. package/out/zero-cache/src/services/auth-attempt-counter.d.ts.map +1 -0
  60. package/out/zero-cache/src/services/auth-attempt-counter.js +61 -0
  61. package/out/zero-cache/src/services/auth-attempt-counter.js.map +1 -0
  62. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +1 -1
  63. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -1
  64. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  65. package/out/zero-cache/src/services/change-source/pg/change-source.js +110 -13
  66. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  67. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +1 -1
  68. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +1 -1
  69. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +15 -8
  70. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  71. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +38 -5
  72. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  73. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  74. package/out/zero-cache/src/services/change-source/pg/schema/init.js +10 -1
  75. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  76. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +4 -0
  77. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  78. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +10 -3
  79. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  80. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +7 -1
  81. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  82. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +23 -2
  83. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  84. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +2 -2
  85. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  86. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +30 -9
  87. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  88. package/out/zero-cache/src/services/change-streamer/change-streamer.js +10 -3
  89. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  90. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts +1 -0
  91. package/out/zero-cache/src/services/change-streamer/subscribe.d.ts.map +1 -1
  92. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +1 -1
  93. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  94. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  95. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  96. package/out/zero-cache/src/services/heapz.js +4 -5
  97. package/out/zero-cache/src/services/heapz.js.map +1 -1
  98. package/out/zero-cache/src/services/mutagen/pusher.js +1 -1
  99. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  100. package/out/zero-cache/src/services/plannerz.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/plannerz.js +3 -7
  102. package/out/zero-cache/src/services/plannerz.js.map +1 -1
  103. package/out/zero-cache/src/services/profz.d.ts.map +1 -1
  104. package/out/zero-cache/src/services/profz.js +4 -13
  105. package/out/zero-cache/src/services/profz.js.map +1 -1
  106. package/out/zero-cache/src/services/replicator/change-processor.js +1 -2
  107. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  108. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  109. package/out/zero-cache/src/services/replicator/incremental-sync.js +3 -3
  110. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  111. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  112. package/out/zero-cache/src/services/statz.js +2 -7
  113. package/out/zero-cache/src/services/statz.js.map +1 -1
  114. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +16 -0
  115. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  116. package/out/zero-cache/src/services/view-syncer/client-handler.js +22 -1
  117. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  118. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +29 -4
  119. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
  120. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +40 -2
  121. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  122. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +10 -2
  123. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  124. package/out/zero-cache/src/services/view-syncer/cvr-store.js +40 -16
  125. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  126. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +8 -0
  127. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  128. package/out/zero-cache/src/services/view-syncer/cvr.js +11 -0
  129. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  130. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.d.ts +35 -0
  131. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.d.ts.map +1 -0
  132. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js +107 -0
  133. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js.map +1 -0
  134. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -2
  135. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  136. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +11 -6
  137. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  138. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  139. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +2 -1
  140. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  141. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts +9 -0
  142. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
  143. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +4 -1
  144. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  145. package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
  146. package/out/zero-cache/src/services/view-syncer/schema/init.js +3 -0
  147. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  148. package/out/zero-cache/src/services/view-syncer/snapshotter.js +1 -1
  149. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  150. package/out/zero-cache/src/services/view-syncer/view-syncer.js +96 -44
  151. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  152. package/out/zero-cache/src/types/client-group-log-id.d.ts +9 -0
  153. package/out/zero-cache/src/types/client-group-log-id.d.ts.map +1 -0
  154. package/out/zero-cache/src/types/client-group-log-id.js +16 -0
  155. package/out/zero-cache/src/types/client-group-log-id.js.map +1 -0
  156. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  157. package/out/zero-cache/src/types/lite.js +1 -0
  158. package/out/zero-cache/src/types/lite.js.map +1 -1
  159. package/out/zero-cache/src/types/pg.d.ts +13 -2
  160. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  161. package/out/zero-cache/src/types/pg.js +2 -2
  162. package/out/zero-cache/src/types/pg.js.map +1 -1
  163. package/out/zero-cache/src/workers/connection.d.ts +1 -0
  164. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  165. package/out/zero-cache/src/workers/connection.js +5 -1
  166. package/out/zero-cache/src/workers/connection.js.map +1 -1
  167. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  168. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +12 -3
  169. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  170. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  171. package/out/zero-cache/src/workers/syncer.js +15 -14
  172. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  173. package/out/zero-client/src/client/inspector/inspector.d.ts +4 -0
  174. package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
  175. package/out/zero-client/src/client/inspector/inspector.js +4 -0
  176. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  177. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +10 -2
  178. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  179. package/out/zero-client/src/client/inspector/lazy-inspector.js +38 -31
  180. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  181. package/out/zero-client/src/client/inspector/query.d.ts +2 -2
  182. package/out/zero-client/src/client/inspector/query.d.ts.map +1 -1
  183. package/out/zero-client/src/client/inspector/query.js +4 -4
  184. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  185. package/out/zero-client/src/client/version.js +1 -1
  186. package/out/zero-client/src/util/nanoid.js +2 -2
  187. package/out/zero-client/src/util/nanoid.js.map +1 -1
  188. package/out/zero-server/src/process-mutations.d.ts +10 -0
  189. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  190. package/out/zero-server/src/process-mutations.js +38 -5
  191. package/out/zero-server/src/process-mutations.js.map +1 -1
  192. package/package.json +1 -1
@@ -6,6 +6,14 @@ import type { ClientSchema } from '../../../../../zero-protocol/src/client-schem
6
6
  import { type ShardID } from '../../../types/shards.ts';
7
7
  import type { TTLClock } from '../ttl-clock.ts';
8
8
  import { type RowID, type RowRecord } from './types.ts';
9
+ /**
10
+ * The user a client group is pinned to: the user of its first validated
11
+ * connection, with `id: null` for a logged-out group. Every later validated
12
+ * connection to the group must be from the same user.
13
+ */
14
+ export type PinnedUser = {
15
+ readonly id: string | null;
16
+ };
9
17
  export type InstancesRow = {
10
18
  clientGroupID: string;
11
19
  version: string;
@@ -16,6 +24,7 @@ export type InstancesRow = {
16
24
  grantedAt: number | null;
17
25
  clientSchema: ClientSchema | null;
18
26
  profileID: string | null;
27
+ pinnedUser?: PinnedUser | null | undefined;
19
28
  };
20
29
  export declare function compareInstancesRows(a: InstancesRow, b: InstancesRow): number;
21
30
  export type ClientsRow = {
@@ -1 +1 @@
1
- {"version":3,"file":"cvr.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/cvr.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cvr.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/cvr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AACrC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,SAAS,EAEf,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mCAAmC,CAAC;AAEzE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,mDAAmD,CAAC;AAEpF,OAAO,EAAY,KAAK,OAAO,EAAC,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,KAAK,KAAK,EACV,KAAK,SAAS,EAGf,MAAM,YAAY,CAAC;AAWpB;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,CAAC;AAEtD,MAAM,MAAM,YAAY,GAAG;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;CAC5C,CAAC;AAgCF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,UAEpE;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAkBF,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,UAM9D;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAElB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAC/C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAGxB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AA+BF,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,UAM9D;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,aAAa,EAAE,QAAQ,GAAG,IAAI,CAAC;CAChC,CAAC;AAgCF,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,UAU9D;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE;QAAC,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,GAAG,IAAI,CAAC;CACjD,CAAC;AAEF,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,KAAK,CAMtD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAO9D;AAED,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,SAAS,GACnB,OAAO,CAoBT;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,UAiBrD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,UAOpD;AAqCD,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF,wBAAsB,cAAc,CAClC,EAAE,EAAE,UAAU,EACd,EAAE,EAAE,QAAQ,CAAC,cAAc,EAC3B,KAAK,EAAE,OAAO,iBAIf"}
@@ -22,7 +22,8 @@ CREATE TABLE ${schema(shard)}.instances (
22
22
  "grantedAt" TIMESTAMPTZ, -- The time at which the current owner was last granted ownership (most recent connection time).
23
23
  "clientSchema" JSONB, -- ClientSchema of the client group
24
24
  "profileID" TEXT, -- Stable profile id ("p..."), falling back to the clientGroupID ("cg{clientGroupID}") for old clients
25
- "deleted" BOOL DEFAULT FALSE -- Tombstone column for deleted CVRs; instances rows are kept longer for usage stats
25
+ "deleted" BOOL DEFAULT FALSE, -- Tombstone column for deleted CVRs; instances rows are kept longer for usage stats
26
+ "pinnedUser" JSONB -- {"id": userID | null} of the first validated connection; NULL until a connection has been validated
26
27
  );
27
28
 
28
29
  -- For garbage collection.
@@ -127,6 +128,8 @@ function rowsRowToRowRecord(rowsRow) {
127
128
  };
128
129
  }
129
130
  function rowRecordToRowsRow(clientGroupID, rowRecord) {
131
+ const { rowKey } = rowRecord.id;
132
+ for (const column in rowKey) if (typeof rowKey[column] === "bigint") throw new Error(`Row key column ${rowRecord.id.table}.${column} of a CVR row is a bigint`);
130
133
  return {
131
134
  clientGroupID,
132
135
  schema: rowRecord.id.schema,
@@ -1 +1 @@
1
- {"version":3,"file":"cvr.js","names":[],"sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/cvr.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {ident} from 'pg-format';\nimport type postgres from 'postgres';\nimport {\n type JSONObject,\n type JSONValue,\n stringify,\n} from '../../../../../shared/src/bigint-json.ts';\nimport type {ReadonlyJSONValue} from '../../../../../shared/src/json.ts';\nimport {stringCompare} from '../../../../../shared/src/string-compare.ts';\nimport type {ClientSchema} from '../../../../../zero-protocol/src/client-schema.ts';\nimport {normalizedKeyOrder, type RowKey} from '../../../types/row-key.ts';\nimport {cvrSchema, type ShardID} from '../../../types/shards.ts';\nimport type {TTLClock} from '../ttl-clock.ts';\nimport {\n type RowID,\n type RowRecord,\n versionFromString,\n versionString,\n} from './types.ts';\n\n// For readability in the sql statements.\nfunction schema(shard: ShardID) {\n return ident(cvrSchema(shard));\n}\n\nfunction createSchema(shard: ShardID) {\n return `CREATE SCHEMA IF NOT EXISTS ${schema(shard)};`;\n}\n\nexport type InstancesRow = {\n clientGroupID: string;\n version: string;\n lastActive: number;\n ttlClock: TTLClock;\n replicaVersion: string | null;\n owner: string | null;\n grantedAt: number | null;\n clientSchema: ClientSchema | null;\n profileID: string | null;\n};\n\nfunction createInstancesTable(shard: ShardID) {\n return /*sql*/ `\nCREATE TABLE ${schema(shard)}.instances (\n \"clientGroupID\" TEXT PRIMARY KEY,\n \"version\" TEXT NOT NULL, -- Sortable representation of CVRVersion, e.g. \"5nbqa2w:09\"\n \"lastActive\" TIMESTAMPTZ NOT NULL, -- For garbage collection\n \"ttlClock\" DOUBLE PRECISION NOT NULL DEFAULT 0, -- The ttl clock gets \"paused\" when disconnected.\n \"replicaVersion\" TEXT, -- Identifies the replica (i.e. initial-sync point) from which the CVR data comes.\n \"owner\" TEXT, -- The ID of the task / server that has been granted ownership of the CVR.\n \"grantedAt\" TIMESTAMPTZ, -- The time at which the current owner was last granted ownership (most recent connection time).\n \"clientSchema\" JSONB, -- ClientSchema of the client group\n \"profileID\" TEXT, -- Stable profile id (\"p...\"), falling back to the clientGroupID (\"cg{clientGroupID}\") for old clients\n \"deleted\" BOOL DEFAULT FALSE -- Tombstone column for deleted CVRs; instances rows are kept longer for usage stats\n);\n\n-- For garbage collection.\nCREATE INDEX instances_last_active\n ON ${schema(shard)}.instances (\"lastActive\") WHERE NOT \"deleted\";\nCREATE INDEX tombstones_last_active\n ON ${schema(shard)}.instances (\"lastActive\") WHERE \"deleted\";\n\n-- For usage stats; the composite index allows a \n-- SELECT COUNT(DISTINCT(\"profileID\")) query to be answered by\n-- an index scan without additional table lookups.\nCREATE INDEX profile_ids_last_active ON ${schema(shard)}.instances (\"lastActive\", \"profileID\")\n WHERE \"profileID\" IS NOT NULL;\n`;\n}\n\nexport function compareInstancesRows(a: InstancesRow, b: InstancesRow) {\n return stringCompare(a.clientGroupID, b.clientGroupID);\n}\n\nexport type ClientsRow = {\n clientGroupID: string;\n clientID: string;\n};\n\nfunction createClientsTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.clients (\n \"clientGroupID\" TEXT,\n \"clientID\" TEXT,\n\n PRIMARY KEY (\"clientGroupID\", \"clientID\"),\n\n CONSTRAINT fk_clients_client_group\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${schema(shard)}.instances(\"clientGroupID\")\n ON DELETE CASCADE\n);\n\n`;\n}\nexport function compareClientsRows(a: ClientsRow, b: ClientsRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n return stringCompare(a.clientID, b.clientID);\n}\n\nexport type QueriesRow = {\n clientGroupID: string;\n queryHash: string;\n // This is the client AST _AFTER_ applying server name transformations.\n clientAST: JSONValue | null;\n queryName: string | null;\n queryArgs: readonly ReadonlyJSONValue[] | null;\n patchVersion: string | null;\n transformationHash: string | null;\n transformationVersion: string | null;\n internal: boolean | null;\n deleted: boolean | null;\n // Optional because (a) old DBs migrated to v17 will start with NULL, and\n // (b) test fixtures predate this column.\n rowSetSignature?: string | null;\n};\n\nfunction createQueriesTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.queries (\n \"clientGroupID\" TEXT,\n \"queryHash\" TEXT, -- this is the hash of the client query AST\n \"clientAST\" JSONB, -- this is nullable as custom queries will not persist an AST\n \"queryName\" TEXT, -- the name of the query if it is a custom query\n \"queryArgs\" JSON, -- the arguments of the query if it is a custom query\n \"patchVersion\" TEXT, -- NULL if only desired but not yet \"got\"\n \"transformationHash\" TEXT,\n \"transformationVersion\" TEXT,\n \"internal\" BOOL, -- If true, no need to track / send patches\n \"deleted\" BOOL, -- put vs del \"got\" query\n \"rowSetSignature\" TEXT, -- Hex XOR of h64([schema,table,rowKey]) for rows in this query (drift detection for Cap)\n\n PRIMARY KEY (\"clientGroupID\", \"queryHash\"),\n\n CONSTRAINT fk_queries_client_group\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${schema(shard)}.instances(\"clientGroupID\")\n ON DELETE CASCADE\n);\n\n-- For catchup patches.\nCREATE INDEX queries_patch_version \n ON ${schema(shard)}.queries (\"patchVersion\" NULLS FIRST);\n`;\n}\n\nexport function compareQueriesRows(a: QueriesRow, b: QueriesRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n return stringCompare(a.queryHash, b.queryHash);\n}\n\nexport type DesiresRow = {\n clientGroupID: string;\n clientID: string;\n queryHash: string;\n patchVersion: string;\n deleted: boolean | null;\n ttl: number | null;\n inactivatedAt: TTLClock | null;\n};\n\nfunction createDesiresTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.desires (\n \"clientGroupID\" TEXT,\n \"clientID\" TEXT,\n \"queryHash\" TEXT,\n \"patchVersion\" TEXT NOT NULL,\n \"deleted\" BOOL, -- put vs del \"desired\" query\n \"ttl\" INTERVAL, -- DEPRECATED: Use ttlMs instead. Time to live for this client\n \"ttlMs\" DOUBLE PRECISION, -- Time to live in milliseconds\n \"inactivatedAt\" TIMESTAMPTZ, -- DEPRECATED: Use inactivatedAtMs instead. Time at which this row was inactivated\n \"inactivatedAtMs\" DOUBLE PRECISION, -- Time at which this row was inactivated (milliseconds since client group start)\n\n PRIMARY KEY (\"clientGroupID\", \"clientID\", \"queryHash\"),\n\n CONSTRAINT fk_desires_query\n FOREIGN KEY(\"clientGroupID\", \"queryHash\")\n REFERENCES ${ident(cvrSchema(shard))}.queries(\"clientGroupID\", \"queryHash\")\n ON DELETE CASCADE\n);\n\n-- For catchup patches.\nCREATE INDEX desires_patch_version\n ON ${schema(shard)}.desires (\"patchVersion\");\n\nCREATE INDEX desires_inactivated_at\n ON ${schema(shard)}.desires (\"inactivatedAt\");\n`;\n}\n\nexport function compareDesiresRows(a: DesiresRow, b: DesiresRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n const clientIDComp = stringCompare(a.clientID, b.clientID);\n if (clientIDComp !== 0) {\n return clientIDComp;\n }\n return stringCompare(a.queryHash, b.queryHash);\n}\n\nexport type RowsRow = {\n clientGroupID: string;\n schema: string;\n table: string;\n rowKey: JSONObject;\n rowVersion: string;\n patchVersion: string;\n refCounts: {[queryHash: string]: number} | null;\n};\n\nexport function rowsRowToRowID(rowsRow: RowsRow): RowID {\n return {\n schema: rowsRow.schema,\n table: rowsRow.table,\n rowKey: rowsRow.rowKey as Record<string, JSONValue>,\n };\n}\n\nexport function rowsRowToRowRecord(rowsRow: RowsRow): RowRecord {\n return {\n id: rowsRowToRowID(rowsRow),\n rowVersion: rowsRow.rowVersion,\n patchVersion: versionFromString(rowsRow.patchVersion),\n refCounts: rowsRow.refCounts,\n };\n}\n\nexport function rowRecordToRowsRow(\n clientGroupID: string,\n rowRecord: RowRecord,\n): RowsRow {\n return {\n clientGroupID,\n schema: rowRecord.id.schema,\n table: rowRecord.id.table,\n rowKey: rowRecord.id.rowKey as Record<string, JSONValue>,\n rowVersion: rowRecord.rowVersion,\n patchVersion: versionString(rowRecord.patchVersion),\n refCounts: rowRecord.refCounts,\n };\n}\n\nexport function compareRowsRows(a: RowsRow, b: RowsRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n const schemaComp = stringCompare(a.schema, b.schema);\n if (schemaComp !== 0) {\n return schemaComp;\n }\n const tableComp = stringCompare(b.table, b.table);\n if (tableComp !== 0) {\n return tableComp;\n }\n return stringCompare(\n stringifySorted(a.rowKey as RowKey),\n stringifySorted(b.rowKey as RowKey),\n );\n}\n\n/**\n * The version of the data in the `cvr.rows` table. This may lag\n * `version` in `cvr.instances` but eventually catches up, modulo\n * exceptional circumstances like a server crash.\n *\n * The `rowsVersion` is tracked in a separate table (as opposed to\n * a column in the `cvr.instances` table) so that general `cvr` updates\n * and `row` updates can be executed independently without serialization\n * conflicts.\n *\n * Note: Although `clientGroupID` logically references the same column in\n * `cvr.instances`, a FOREIGN KEY constraint must not be declared as the\n * `cvr.rows` TABLE needs to be updated without affecting the\n * `SELECT ... FOR UPDATE` lock when `cvr.instances` is updated.\n */\nexport function createRowsVersionTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.\"rowsVersion\" (\n \"clientGroupID\" TEXT PRIMARY KEY,\n \"version\" TEXT NOT NULL\n);\n`;\n}\n\n/**\n * CVR `rows` are updated asynchronously from the CVR metadata\n * (i.e. `instances`). The `rowsVersion` table is updated atomically with\n * updates to the `rows` data.\n */\nfunction createRowsTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.rows (\n \"clientGroupID\" TEXT,\n \"schema\" TEXT,\n \"table\" TEXT,\n \"rowKey\" JSONB,\n \"rowVersion\" TEXT NOT NULL,\n \"patchVersion\" TEXT NOT NULL,\n \"refCounts\" JSONB, -- {[queryHash: string]: number}, NULL for tombstone\n\n PRIMARY KEY (\"clientGroupID\", \"schema\", \"table\", \"rowKey\"),\n\n CONSTRAINT fk_rows_client_group\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${schema(shard)}.\"rowsVersion\" (\"clientGroupID\")\n ON DELETE CASCADE\n);\n\n-- For catchup patches.\nCREATE INDEX row_patch_version \n ON ${schema(shard)}.rows (\"patchVersion\");\n\n-- For listing rows returned by one or more query hashes. e.g.\n-- SELECT * FROM cvr_shard.rows WHERE \"refCounts\" ?| array[...queryHashes...];\nCREATE INDEX row_ref_counts ON ${schema(shard)}.rows \n USING GIN (\"refCounts\");\n`;\n}\n\nexport type RowsVersionRow = {\n clientGroupID: string;\n version: string;\n};\n\nfunction createTables(shard: ShardID) {\n return (\n createSchema(shard) +\n createInstancesTable(shard) +\n createClientsTable(shard) +\n createQueriesTable(shard) +\n createDesiresTable(shard) +\n createRowsVersionTable(shard) +\n createRowsTable(shard)\n );\n}\n\nexport async function setupCVRTables(\n lc: LogContext,\n db: postgres.TransactionSql,\n shard: ShardID,\n) {\n lc.info?.(`Setting up CVR tables`);\n await db.unsafe(createTables(shard));\n}\n\nfunction stringifySorted(r: RowKey) {\n return stringify(normalizedKeyOrder(r));\n}\n"],"mappings":";;;;;;AAsBA,SAAS,OAAO,OAAgB;CAC9B,OAAO,MAAM,UAAU,KAAK,CAAC;AAC/B;AAEA,SAAS,aAAa,OAAgB;CACpC,OAAO,+BAA+B,OAAO,KAAK,EAAE;AACtD;AAcA,SAAS,qBAAqB,OAAgB;CAC5C,OAAe;eACF,OAAO,KAAK,EAAE;;;;;;;;;;;;;;;OAetB,OAAO,KAAK,EAAE;;OAEd,OAAO,KAAK,EAAE;;;;;0CAKqB,OAAO,KAAK,EAAE;;;AAGxD;AAWA,SAAS,mBAAmB,OAAgB;CAC1C,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;iBAQZ,OAAO,KAAK,EAAE;;;;;AAK/B;AA0BA,SAAS,mBAAmB,OAAgB;CAC1C,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;;;;;;;;;;iBAiBZ,OAAO,KAAK,EAAE;;;;;;OAMxB,OAAO,KAAK,EAAE;;AAErB;AAoBA,SAAS,mBAAmB,OAAgB;CAC1C,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;;;;;;;;iBAeZ,MAAM,UAAU,KAAK,CAAC,EAAE;;;;;;OAMlC,OAAO,KAAK,EAAE;;;OAGd,OAAO,KAAK,EAAE;;AAErB;AAwBA,SAAgB,eAAe,SAAyB;CACtD,OAAO;EACL,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EACf,QAAQ,QAAQ;CAClB;AACF;AAEA,SAAgB,mBAAmB,SAA6B;CAC9D,OAAO;EACL,IAAI,eAAe,OAAO;EAC1B,YAAY,QAAQ;EACpB,cAAc,kBAAkB,QAAQ,YAAY;EACpD,WAAW,QAAQ;CACrB;AACF;AAEA,SAAgB,mBACd,eACA,WACS;CACT,OAAO;EACL;EACA,QAAQ,UAAU,GAAG;EACrB,OAAO,UAAU,GAAG;EACpB,QAAQ,UAAU,GAAG;EACrB,YAAY,UAAU;EACtB,cAAc,cAAc,UAAU,YAAY;EAClD,WAAW,UAAU;CACvB;AACF;;;;;;;;;;;;;;;;AAoCA,SAAgB,uBAAuB,OAAgB;CACrD,OAAO;eACM,OAAO,KAAK,EAAE;;;;;AAK7B;;;;;;AAOA,SAAS,gBAAgB,OAAgB;CACvC,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;;;;;;iBAaZ,OAAO,KAAK,EAAE;;;;;;OAMxB,OAAO,KAAK,EAAE;;;;iCAIY,OAAO,KAAK,EAAE;;;AAG/C;AAOA,SAAS,aAAa,OAAgB;CACpC,OACE,aAAa,KAAK,IAClB,qBAAqB,KAAK,IAC1B,mBAAmB,KAAK,IACxB,mBAAmB,KAAK,IACxB,mBAAmB,KAAK,IACxB,uBAAuB,KAAK,IAC5B,gBAAgB,KAAK;AAEzB;AAEA,eAAsB,eACpB,IACA,IACA,OACA;CACA,GAAG,OAAO,uBAAuB;CACjC,MAAM,GAAG,OAAO,aAAa,KAAK,CAAC;AACrC"}
1
+ {"version":3,"file":"cvr.js","names":[],"sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/cvr.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {ident} from 'pg-format';\nimport type postgres from 'postgres';\nimport {\n type JSONObject,\n type JSONValue,\n stringify,\n} from '../../../../../shared/src/bigint-json.ts';\nimport type {ReadonlyJSONValue} from '../../../../../shared/src/json.ts';\nimport {stringCompare} from '../../../../../shared/src/string-compare.ts';\nimport type {ClientSchema} from '../../../../../zero-protocol/src/client-schema.ts';\nimport {normalizedKeyOrder, type RowKey} from '../../../types/row-key.ts';\nimport {cvrSchema, type ShardID} from '../../../types/shards.ts';\nimport type {TTLClock} from '../ttl-clock.ts';\nimport {\n type RowID,\n type RowRecord,\n versionFromString,\n versionString,\n} from './types.ts';\n\n// For readability in the sql statements.\nfunction schema(shard: ShardID) {\n return ident(cvrSchema(shard));\n}\n\nfunction createSchema(shard: ShardID) {\n return `CREATE SCHEMA IF NOT EXISTS ${schema(shard)};`;\n}\n\n/**\n * The user a client group is pinned to: the user of its first validated\n * connection, with `id: null` for a logged-out group. Every later validated\n * connection to the group must be from the same user.\n */\nexport type PinnedUser = {readonly id: string | null};\n\nexport type InstancesRow = {\n clientGroupID: string;\n version: string;\n lastActive: number;\n ttlClock: TTLClock;\n replicaVersion: string | null;\n owner: string | null;\n grantedAt: number | null;\n clientSchema: ClientSchema | null;\n profileID: string | null;\n // Optional because old DBs and test fixtures predate this column.\n pinnedUser?: PinnedUser | null | undefined;\n};\n\nfunction createInstancesTable(shard: ShardID) {\n return /*sql*/ `\nCREATE TABLE ${schema(shard)}.instances (\n \"clientGroupID\" TEXT PRIMARY KEY,\n \"version\" TEXT NOT NULL, -- Sortable representation of CVRVersion, e.g. \"5nbqa2w:09\"\n \"lastActive\" TIMESTAMPTZ NOT NULL, -- For garbage collection\n \"ttlClock\" DOUBLE PRECISION NOT NULL DEFAULT 0, -- The ttl clock gets \"paused\" when disconnected.\n \"replicaVersion\" TEXT, -- Identifies the replica (i.e. initial-sync point) from which the CVR data comes.\n \"owner\" TEXT, -- The ID of the task / server that has been granted ownership of the CVR.\n \"grantedAt\" TIMESTAMPTZ, -- The time at which the current owner was last granted ownership (most recent connection time).\n \"clientSchema\" JSONB, -- ClientSchema of the client group\n \"profileID\" TEXT, -- Stable profile id (\"p...\"), falling back to the clientGroupID (\"cg{clientGroupID}\") for old clients\n \"deleted\" BOOL DEFAULT FALSE, -- Tombstone column for deleted CVRs; instances rows are kept longer for usage stats\n \"pinnedUser\" JSONB -- {\"id\": userID | null} of the first validated connection; NULL until a connection has been validated\n);\n\n-- For garbage collection.\nCREATE INDEX instances_last_active\n ON ${schema(shard)}.instances (\"lastActive\") WHERE NOT \"deleted\";\nCREATE INDEX tombstones_last_active\n ON ${schema(shard)}.instances (\"lastActive\") WHERE \"deleted\";\n\n-- For usage stats; the composite index allows a \n-- SELECT COUNT(DISTINCT(\"profileID\")) query to be answered by\n-- an index scan without additional table lookups.\nCREATE INDEX profile_ids_last_active ON ${schema(shard)}.instances (\"lastActive\", \"profileID\")\n WHERE \"profileID\" IS NOT NULL;\n`;\n}\n\nexport function compareInstancesRows(a: InstancesRow, b: InstancesRow) {\n return stringCompare(a.clientGroupID, b.clientGroupID);\n}\n\nexport type ClientsRow = {\n clientGroupID: string;\n clientID: string;\n};\n\nfunction createClientsTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.clients (\n \"clientGroupID\" TEXT,\n \"clientID\" TEXT,\n\n PRIMARY KEY (\"clientGroupID\", \"clientID\"),\n\n CONSTRAINT fk_clients_client_group\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${schema(shard)}.instances(\"clientGroupID\")\n ON DELETE CASCADE\n);\n\n`;\n}\nexport function compareClientsRows(a: ClientsRow, b: ClientsRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n return stringCompare(a.clientID, b.clientID);\n}\n\nexport type QueriesRow = {\n clientGroupID: string;\n queryHash: string;\n // This is the client AST _AFTER_ applying server name transformations.\n clientAST: JSONValue | null;\n queryName: string | null;\n queryArgs: readonly ReadonlyJSONValue[] | null;\n patchVersion: string | null;\n transformationHash: string | null;\n transformationVersion: string | null;\n internal: boolean | null;\n deleted: boolean | null;\n // Optional because (a) old DBs migrated to v17 will start with NULL, and\n // (b) test fixtures predate this column.\n rowSetSignature?: string | null;\n};\n\nfunction createQueriesTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.queries (\n \"clientGroupID\" TEXT,\n \"queryHash\" TEXT, -- this is the hash of the client query AST\n \"clientAST\" JSONB, -- this is nullable as custom queries will not persist an AST\n \"queryName\" TEXT, -- the name of the query if it is a custom query\n \"queryArgs\" JSON, -- the arguments of the query if it is a custom query\n \"patchVersion\" TEXT, -- NULL if only desired but not yet \"got\"\n \"transformationHash\" TEXT,\n \"transformationVersion\" TEXT,\n \"internal\" BOOL, -- If true, no need to track / send patches\n \"deleted\" BOOL, -- put vs del \"got\" query\n \"rowSetSignature\" TEXT, -- Hex XOR of h64([schema,table,rowKey]) for rows in this query (drift detection for Cap)\n\n PRIMARY KEY (\"clientGroupID\", \"queryHash\"),\n\n CONSTRAINT fk_queries_client_group\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${schema(shard)}.instances(\"clientGroupID\")\n ON DELETE CASCADE\n);\n\n-- For catchup patches.\nCREATE INDEX queries_patch_version \n ON ${schema(shard)}.queries (\"patchVersion\" NULLS FIRST);\n`;\n}\n\nexport function compareQueriesRows(a: QueriesRow, b: QueriesRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n return stringCompare(a.queryHash, b.queryHash);\n}\n\nexport type DesiresRow = {\n clientGroupID: string;\n clientID: string;\n queryHash: string;\n patchVersion: string;\n deleted: boolean | null;\n ttl: number | null;\n inactivatedAt: TTLClock | null;\n};\n\nfunction createDesiresTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.desires (\n \"clientGroupID\" TEXT,\n \"clientID\" TEXT,\n \"queryHash\" TEXT,\n \"patchVersion\" TEXT NOT NULL,\n \"deleted\" BOOL, -- put vs del \"desired\" query\n \"ttl\" INTERVAL, -- DEPRECATED: Use ttlMs instead. Time to live for this client\n \"ttlMs\" DOUBLE PRECISION, -- Time to live in milliseconds\n \"inactivatedAt\" TIMESTAMPTZ, -- DEPRECATED: Use inactivatedAtMs instead. Time at which this row was inactivated\n \"inactivatedAtMs\" DOUBLE PRECISION, -- Time at which this row was inactivated (milliseconds since client group start)\n\n PRIMARY KEY (\"clientGroupID\", \"clientID\", \"queryHash\"),\n\n CONSTRAINT fk_desires_query\n FOREIGN KEY(\"clientGroupID\", \"queryHash\")\n REFERENCES ${ident(cvrSchema(shard))}.queries(\"clientGroupID\", \"queryHash\")\n ON DELETE CASCADE\n);\n\n-- For catchup patches.\nCREATE INDEX desires_patch_version\n ON ${schema(shard)}.desires (\"patchVersion\");\n\nCREATE INDEX desires_inactivated_at\n ON ${schema(shard)}.desires (\"inactivatedAt\");\n`;\n}\n\nexport function compareDesiresRows(a: DesiresRow, b: DesiresRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n const clientIDComp = stringCompare(a.clientID, b.clientID);\n if (clientIDComp !== 0) {\n return clientIDComp;\n }\n return stringCompare(a.queryHash, b.queryHash);\n}\n\nexport type RowsRow = {\n clientGroupID: string;\n schema: string;\n table: string;\n rowKey: JSONObject;\n rowVersion: string;\n patchVersion: string;\n refCounts: {[queryHash: string]: number} | null;\n};\n\nexport function rowsRowToRowID(rowsRow: RowsRow): RowID {\n return {\n schema: rowsRow.schema,\n table: rowsRow.table,\n rowKey: rowsRow.rowKey as Record<string, JSONValue>,\n };\n}\n\nexport function rowsRowToRowRecord(rowsRow: RowsRow): RowRecord {\n return {\n id: rowsRowToRowID(rowsRow),\n rowVersion: rowsRow.rowVersion,\n patchVersion: versionFromString(rowsRow.patchVersion),\n refCounts: rowsRow.refCounts,\n };\n}\n\nexport function rowRecordToRowsRow(\n clientGroupID: string,\n rowRecord: RowRecord,\n): RowsRow {\n // CVRs are read with plain JSON numbers (see `plainJSON`), which would round\n // an integer beyond the safe range.\n const {rowKey} = rowRecord.id;\n for (const column in rowKey) {\n if (typeof rowKey[column] === 'bigint') {\n throw new Error(\n `Row key column ${rowRecord.id.table}.${column} of a CVR row is a bigint`,\n );\n }\n }\n return {\n clientGroupID,\n schema: rowRecord.id.schema,\n table: rowRecord.id.table,\n rowKey: rowRecord.id.rowKey as Record<string, JSONValue>,\n rowVersion: rowRecord.rowVersion,\n patchVersion: versionString(rowRecord.patchVersion),\n refCounts: rowRecord.refCounts,\n };\n}\n\nexport function compareRowsRows(a: RowsRow, b: RowsRow) {\n const clientGroupIDComp = stringCompare(a.clientGroupID, b.clientGroupID);\n if (clientGroupIDComp !== 0) {\n return clientGroupIDComp;\n }\n const schemaComp = stringCompare(a.schema, b.schema);\n if (schemaComp !== 0) {\n return schemaComp;\n }\n const tableComp = stringCompare(b.table, b.table);\n if (tableComp !== 0) {\n return tableComp;\n }\n return stringCompare(\n stringifySorted(a.rowKey as RowKey),\n stringifySorted(b.rowKey as RowKey),\n );\n}\n\n/**\n * The version of the data in the `cvr.rows` table. This may lag\n * `version` in `cvr.instances` but eventually catches up, modulo\n * exceptional circumstances like a server crash.\n *\n * The `rowsVersion` is tracked in a separate table (as opposed to\n * a column in the `cvr.instances` table) so that general `cvr` updates\n * and `row` updates can be executed independently without serialization\n * conflicts.\n *\n * Note: Although `clientGroupID` logically references the same column in\n * `cvr.instances`, a FOREIGN KEY constraint must not be declared as the\n * `cvr.rows` TABLE needs to be updated without affecting the\n * `SELECT ... FOR UPDATE` lock when `cvr.instances` is updated.\n */\nexport function createRowsVersionTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.\"rowsVersion\" (\n \"clientGroupID\" TEXT PRIMARY KEY,\n \"version\" TEXT NOT NULL\n);\n`;\n}\n\n/**\n * CVR `rows` are updated asynchronously from the CVR metadata\n * (i.e. `instances`). The `rowsVersion` table is updated atomically with\n * updates to the `rows` data.\n */\nfunction createRowsTable(shard: ShardID) {\n return `\nCREATE TABLE ${schema(shard)}.rows (\n \"clientGroupID\" TEXT,\n \"schema\" TEXT,\n \"table\" TEXT,\n \"rowKey\" JSONB,\n \"rowVersion\" TEXT NOT NULL,\n \"patchVersion\" TEXT NOT NULL,\n \"refCounts\" JSONB, -- {[queryHash: string]: number}, NULL for tombstone\n\n PRIMARY KEY (\"clientGroupID\", \"schema\", \"table\", \"rowKey\"),\n\n CONSTRAINT fk_rows_client_group\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${schema(shard)}.\"rowsVersion\" (\"clientGroupID\")\n ON DELETE CASCADE\n);\n\n-- For catchup patches.\nCREATE INDEX row_patch_version \n ON ${schema(shard)}.rows (\"patchVersion\");\n\n-- For listing rows returned by one or more query hashes. e.g.\n-- SELECT * FROM cvr_shard.rows WHERE \"refCounts\" ?| array[...queryHashes...];\nCREATE INDEX row_ref_counts ON ${schema(shard)}.rows \n USING GIN (\"refCounts\");\n`;\n}\n\nexport type RowsVersionRow = {\n clientGroupID: string;\n version: string;\n};\n\nfunction createTables(shard: ShardID) {\n return (\n createSchema(shard) +\n createInstancesTable(shard) +\n createClientsTable(shard) +\n createQueriesTable(shard) +\n createDesiresTable(shard) +\n createRowsVersionTable(shard) +\n createRowsTable(shard)\n );\n}\n\nexport async function setupCVRTables(\n lc: LogContext,\n db: postgres.TransactionSql,\n shard: ShardID,\n) {\n lc.info?.(`Setting up CVR tables`);\n await db.unsafe(createTables(shard));\n}\n\nfunction stringifySorted(r: RowKey) {\n return stringify(normalizedKeyOrder(r));\n}\n"],"mappings":";;;;;;AAsBA,SAAS,OAAO,OAAgB;CAC9B,OAAO,MAAM,UAAU,KAAK,CAAC;AAC/B;AAEA,SAAS,aAAa,OAAgB;CACpC,OAAO,+BAA+B,OAAO,KAAK,EAAE;AACtD;AAuBA,SAAS,qBAAqB,OAAgB;CAC5C,OAAe;eACF,OAAO,KAAK,EAAE;;;;;;;;;;;;;;;;OAgBtB,OAAO,KAAK,EAAE;;OAEd,OAAO,KAAK,EAAE;;;;;0CAKqB,OAAO,KAAK,EAAE;;;AAGxD;AAWA,SAAS,mBAAmB,OAAgB;CAC1C,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;iBAQZ,OAAO,KAAK,EAAE;;;;;AAK/B;AA0BA,SAAS,mBAAmB,OAAgB;CAC1C,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;;;;;;;;;;iBAiBZ,OAAO,KAAK,EAAE;;;;;;OAMxB,OAAO,KAAK,EAAE;;AAErB;AAoBA,SAAS,mBAAmB,OAAgB;CAC1C,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;;;;;;;;iBAeZ,MAAM,UAAU,KAAK,CAAC,EAAE;;;;;;OAMlC,OAAO,KAAK,EAAE;;;OAGd,OAAO,KAAK,EAAE;;AAErB;AAwBA,SAAgB,eAAe,SAAyB;CACtD,OAAO;EACL,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EACf,QAAQ,QAAQ;CAClB;AACF;AAEA,SAAgB,mBAAmB,SAA6B;CAC9D,OAAO;EACL,IAAI,eAAe,OAAO;EAC1B,YAAY,QAAQ;EACpB,cAAc,kBAAkB,QAAQ,YAAY;EACpD,WAAW,QAAQ;CACrB;AACF;AAEA,SAAgB,mBACd,eACA,WACS;CAGT,MAAM,EAAC,WAAU,UAAU;CAC3B,KAAK,MAAM,UAAU,QACnB,IAAI,OAAO,OAAO,YAAY,UAC5B,MAAM,IAAI,MACR,kBAAkB,UAAU,GAAG,MAAM,GAAG,OAAO,0BACjD;CAGJ,OAAO;EACL;EACA,QAAQ,UAAU,GAAG;EACrB,OAAO,UAAU,GAAG;EACpB,QAAQ,UAAU,GAAG;EACrB,YAAY,UAAU;EACtB,cAAc,cAAc,UAAU,YAAY;EAClD,WAAW,UAAU;CACvB;AACF;;;;;;;;;;;;;;;;AAoCA,SAAgB,uBAAuB,OAAgB;CACrD,OAAO;eACM,OAAO,KAAK,EAAE;;;;;AAK7B;;;;;;AAOA,SAAS,gBAAgB,OAAgB;CACvC,OAAO;eACM,OAAO,KAAK,EAAE;;;;;;;;;;;;;iBAaZ,OAAO,KAAK,EAAE;;;;;;OAMxB,OAAO,KAAK,EAAE;;;;iCAIY,OAAO,KAAK,EAAE;;;AAG/C;AAOA,SAAS,aAAa,OAAgB;CACpC,OACE,aAAa,KAAK,IAClB,qBAAqB,KAAK,IAC1B,mBAAmB,KAAK,IACxB,mBAAmB,KAAK,IACxB,mBAAmB,KAAK,IACxB,uBAAuB,KAAK,IAC5B,gBAAgB,KAAK;AAEzB;AAEA,eAAsB,eACpB,IACA,IACA,OACA;CACA,GAAG,OAAO,uBAAuB;CACjC,MAAM,GAAG,OAAO,aAAa,KAAK,CAAC;AACrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAY,KAAK,OAAO,EAAC,MAAM,0BAA0B,CAAC;AAGjE,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,UAAU,EACf,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,IAAI,CAAC,CA4Pf"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAY,KAAK,OAAO,EAAC,MAAM,0BAA0B,CAAC;AAGjE,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,UAAU,EACf,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,IAAI,CAAC,CAuQf"}
@@ -133,6 +133,9 @@ async function initViewSyncerSchema(log, db, shard) {
133
133
  },
134
134
  17: { migrateSchema: async (_, sql) => {
135
135
  await sql`ALTER TABLE ${sql(schema)}.queries ADD COLUMN "rowSetSignature" TEXT`;
136
+ } },
137
+ 18: { migrateSchema: async (_, sql) => {
138
+ await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN "pinnedUser" JSONB`;
136
139
  } }
137
140
  });
138
141
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","names":[],"sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/init.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {PendingQuery, Row} from 'postgres';\nimport {\n runSchemaMigrations,\n type IncrementalMigrationMap,\n type Migration,\n} from '../../../db/migration.ts';\nimport type {PostgresDB} from '../../../types/pg.ts';\nimport {cvrSchema, type ShardID} from '../../../types/shards.ts';\nimport {createRowsVersionTable, setupCVRTables} from './cvr.ts';\n\nexport async function initViewSyncerSchema(\n log: LogContext,\n db: PostgresDB,\n shard: ShardID,\n): Promise<void> {\n const schema = cvrSchema(shard);\n\n const setupMigration: Migration = {\n migrateSchema: (lc, tx) => setupCVRTables(lc, tx, shard),\n minSafeVersion: 1,\n };\n\n const migrateV1toV2: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"replicaVersion\" TEXT`;\n },\n };\n\n const migrateV2ToV3: Migration = {\n migrateSchema: async (_, tx) => {\n await tx.unsafe(createRowsVersionTable(shard));\n },\n\n /** Populates the cvr.rowsVersion table with versions from cvr.instances. */\n migrateData: async (lc, tx) => {\n const pending: PendingQuery<Row[]>[] = [];\n for await (const versions of tx<\n {clientGroupID: string; version: string}[]\n >`\n SELECT \"clientGroupID\", \"version\" FROM ${tx(schema)}.instances`.cursor(\n 5000,\n )) {\n for (const version of versions) {\n pending.push(\n tx`INSERT INTO ${tx(schema)}.\"rowsVersion\" ${tx(version)} \n ON CONFLICT (\"clientGroupID\")\n DO UPDATE SET ${tx(version)}`.execute(),\n );\n }\n }\n lc.info?.(`initializing rowsVersion for ${pending.length} cvrs`);\n await Promise.all(pending);\n },\n };\n\n const migrateV3ToV4: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"owner\" TEXT`;\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"grantedAt\" TIMESTAMPTZ`;\n },\n };\n\n const migrateV5ToV6: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`\n ALTER TABLE ${tx(schema)}.\"rows\"\n DROP CONSTRAINT fk_rows_client_group`;\n await tx`\n ALTER TABLE ${tx(schema)}.\"rowsVersion\"\n DROP CONSTRAINT fk_rows_version_client_group`;\n },\n };\n\n const migrateV6ToV7: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.desires ADD \"expiresAt\" TIMESTAMPTZ`;\n await tx`ALTER TABLE ${tx(\n schema,\n )}.desires ADD \"inactivatedAt\" TIMESTAMPTZ`;\n await tx`ALTER TABLE ${tx(schema)}.desires ADD \"ttl\" INTERVAL`;\n\n await tx`CREATE INDEX desires_expires_at ON ${tx(\n schema,\n )}.desires (\"expiresAt\")`;\n await tx`CREATE INDEX desires_inactivated_at ON ${tx(\n schema,\n )}.desires (\"inactivatedAt\")`;\n },\n };\n\n const migrateV7ToV8: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(\n schema,\n )}.\"desires\" DROP CONSTRAINT fk_desires_client`;\n },\n };\n\n const migrateV8ToV9: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"clientSchema\" JSONB`;\n },\n };\n\n const migrateV9ToV10: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.queries ADD \"queryName\" TEXT`;\n await tx`ALTER TABLE ${tx(schema)}.queries ADD \"queryArgs\" JSONB`;\n await tx`ALTER TABLE ${tx(schema)}.queries ALTER COLUMN \"clientAST\" DROP NOT NULL`;\n },\n };\n\n const migrateV10ToV11: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`DROP INDEX IF EXISTS ${tx(schema)}.desires_expires_at`;\n await tx`ALTER TABLE ${tx(schema)}.desires DROP COLUMN \"expiresAt\"`;\n await tx`DROP INDEX IF EXISTS ${tx(schema)}.client_patch_version`;\n await tx`ALTER TABLE ${tx(schema)}.clients DROP COLUMN \"patchVersion\"`;\n await tx`ALTER TABLE ${tx(schema)}.clients DROP COLUMN \"deleted\"`;\n },\n };\n\n const migratedV11ToV12: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.queries ALTER COLUMN \"queryArgs\" TYPE JSON USING \"queryArgs\"::JSON`;\n },\n };\n\n const migratedV12ToV13: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD COLUMN \"ttlClock\" DOUBLE PRECISION NOT NULL DEFAULT 0`;\n },\n };\n\n const migratedV13ToV14: Migration = {\n migrateSchema: async (_, sql) => {\n await sql`\n CREATE INDEX instances_last_active ON ${sql(schema)}.instances (\"lastActive\");\n `;\n\n // Update / add foreign key constraints to cascade deletes.\n for (const [table, reference] of [\n ['clients', 'instances'],\n ['queries', 'instances'],\n ['rows', 'rowsVersion'],\n ] as [string, string][]) {\n const constraint = sql(`fk_${table}_client_group`);\n await sql`\n ALTER TABLE ${sql(schema)}.${sql(table)} DROP CONSTRAINT IF EXISTS ${constraint}`;\n await sql`\n ALTER TABLE ${sql(schema)}.${sql(table)} ADD CONSTRAINT ${constraint}\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${sql(schema)}.${sql(reference)} (\"clientGroupID\")\n ON DELETE CASCADE;\n `;\n }\n },\n };\n\n const migratedV14ToV15: Migration = {\n migrateSchema: async (_, sql) => {\n // Add new columns for storing inactivatedAt and ttl in milliseconds.\n // This avoids postgres.js type conversion issues with TIMESTAMPTZ and INTERVAL.\n await sql`ALTER TABLE ${sql(schema)}.desires \n ADD COLUMN \"inactivatedAtMs\" DOUBLE PRECISION`;\n await sql`ALTER TABLE ${sql(schema)}.desires \n ADD COLUMN \"ttlMs\" DOUBLE PRECISION`;\n },\n // Migrate existing data: convert TIMESTAMPTZ to milliseconds for inactivatedAt\n // and INTERVAL to milliseconds for ttl\n // Note: EXTRACT(EPOCH FROM NULL) returns NULL, so NULL values are preserved\n migrateData: async (lc, sql) => {\n lc.info?.(\n 'Migrating desires.inactivatedAt to inactivatedAtMs and ttl to ttlMs',\n );\n await sql`\n UPDATE ${sql(schema)}.desires\n SET \"inactivatedAtMs\" = EXTRACT(EPOCH FROM \"inactivatedAt\") * 1000,\n \"ttlMs\" = EXTRACT(EPOCH FROM \"ttl\") * 1000\n `;\n },\n };\n\n const migratedV15ToV16: Migration = {\n migrateSchema: async (_, sql) => {\n await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN \"profileID\" TEXT`;\n await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN \"deleted\" BOOL DEFAULT FALSE`;\n\n // Recreate the instances_last_active index to exclude tombstones\n await sql`\n DROP INDEX IF EXISTS ${sql(schema)}.instances_last_active`;\n await sql`\n CREATE INDEX instances_last_active ON ${sql(schema)}.instances (\"lastActive\")\n WHERE NOT \"deleted\"`;\n await sql`\n CREATE INDEX tombstones_last_active ON ${sql(schema)}.instances (\"lastActive\")\n WHERE \"deleted\"`;\n await sql`\n CREATE INDEX profile_ids_last_active ON ${sql(schema)}.instances (\"lastActive\", \"profileID\")\n WHERE \"profileID\" IS NOT NULL`;\n },\n\n // Backfill profileIDs to the `cg${clientGroupID}`, as is done for\n // client groups from old zero-clients that don't send a profileID.\n migrateData: async (lc, sql) => {\n lc.info?.('Backfilling instance.profileIDs');\n await sql`\n UPDATE ${sql(schema)}.instances\n SET \"profileID\" = 'cg' || \"clientGroupID\"\n WHERE \"profileID\" IS NULL\n `;\n },\n };\n\n const migratedV16ToV17: Migration = {\n migrateSchema: async (_, sql) => {\n await sql`ALTER TABLE ${sql(schema)}.queries ADD COLUMN \"rowSetSignature\" TEXT`;\n },\n };\n\n const schemaVersionMigrationMap: IncrementalMigrationMap = {\n 2: migrateV1toV2,\n 3: migrateV2ToV3,\n 4: migrateV3ToV4,\n // v5 enables asynchronous row-record flushing, and thus relies on\n // the logic that updates and checks the rowsVersion table in v3.\n 5: {minSafeVersion: 3},\n 6: migrateV5ToV6,\n 7: migrateV6ToV7,\n 8: migrateV7ToV8,\n 9: migrateV8ToV9,\n // v10 adds queryName and queryArgs to the queries table to support\n // custom queries. clientAST is now optional to support migrating\n // off client queries.\n 10: migrateV9ToV10,\n // V11 removes the deprecated queries.\"expiresAt\", clients.\"patchVersion\",\n // clients.\"deleted\" columns.\n 11: migrateV10ToV11,\n 12: migratedV11ToV12,\n // V13 adds instances.\"ttlClock\"\n 13: migratedV12ToV13,\n // V14 adds an index on instances.\"lastActive\" and a FK constraint\n // from rows.\"clientGroupID\" to rowsVersion.\"clientGroupID\" for\n // garbage collection\n 14: migratedV13ToV14,\n // V15 adds desires.\"inactivatedAtTTLClock\" to store TTLClock values\n // directly as DOUBLE PRECISION, avoiding postgres.js TIMESTAMPTZ\n // type conversion issues\n 15: migratedV14ToV15,\n // V16 adds instances.\"profileID\" and a corresponding index for estimating\n // active user counts more accurately for apps that use memstore.\n 16: migratedV15ToV16,\n // V17 adds queries.\"rowSetSignature\" — XOR'd hash of row IDs attached to\n // each query, used to detect drift on re-hydration of queries containing\n // the Cap operator.\n 17: migratedV16ToV17,\n };\n\n await runSchemaMigrations(\n log,\n 'view-syncer',\n cvrSchema(shard),\n db,\n setupMigration,\n schemaVersionMigrationMap,\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"init.js","names":[],"sources":["../../../../../../../zero-cache/src/services/view-syncer/schema/init.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {PendingQuery, Row} from 'postgres';\nimport {\n runSchemaMigrations,\n type IncrementalMigrationMap,\n type Migration,\n} from '../../../db/migration.ts';\nimport type {PostgresDB} from '../../../types/pg.ts';\nimport {cvrSchema, type ShardID} from '../../../types/shards.ts';\nimport {createRowsVersionTable, setupCVRTables} from './cvr.ts';\n\nexport async function initViewSyncerSchema(\n log: LogContext,\n db: PostgresDB,\n shard: ShardID,\n): Promise<void> {\n const schema = cvrSchema(shard);\n\n const setupMigration: Migration = {\n migrateSchema: (lc, tx) => setupCVRTables(lc, tx, shard),\n minSafeVersion: 1,\n };\n\n const migrateV1toV2: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"replicaVersion\" TEXT`;\n },\n };\n\n const migrateV2ToV3: Migration = {\n migrateSchema: async (_, tx) => {\n await tx.unsafe(createRowsVersionTable(shard));\n },\n\n /** Populates the cvr.rowsVersion table with versions from cvr.instances. */\n migrateData: async (lc, tx) => {\n const pending: PendingQuery<Row[]>[] = [];\n for await (const versions of tx<\n {clientGroupID: string; version: string}[]\n >`\n SELECT \"clientGroupID\", \"version\" FROM ${tx(schema)}.instances`.cursor(\n 5000,\n )) {\n for (const version of versions) {\n pending.push(\n tx`INSERT INTO ${tx(schema)}.\"rowsVersion\" ${tx(version)} \n ON CONFLICT (\"clientGroupID\")\n DO UPDATE SET ${tx(version)}`.execute(),\n );\n }\n }\n lc.info?.(`initializing rowsVersion for ${pending.length} cvrs`);\n await Promise.all(pending);\n },\n };\n\n const migrateV3ToV4: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"owner\" TEXT`;\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"grantedAt\" TIMESTAMPTZ`;\n },\n };\n\n const migrateV5ToV6: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`\n ALTER TABLE ${tx(schema)}.\"rows\"\n DROP CONSTRAINT fk_rows_client_group`;\n await tx`\n ALTER TABLE ${tx(schema)}.\"rowsVersion\"\n DROP CONSTRAINT fk_rows_version_client_group`;\n },\n };\n\n const migrateV6ToV7: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.desires ADD \"expiresAt\" TIMESTAMPTZ`;\n await tx`ALTER TABLE ${tx(\n schema,\n )}.desires ADD \"inactivatedAt\" TIMESTAMPTZ`;\n await tx`ALTER TABLE ${tx(schema)}.desires ADD \"ttl\" INTERVAL`;\n\n await tx`CREATE INDEX desires_expires_at ON ${tx(\n schema,\n )}.desires (\"expiresAt\")`;\n await tx`CREATE INDEX desires_inactivated_at ON ${tx(\n schema,\n )}.desires (\"inactivatedAt\")`;\n },\n };\n\n const migrateV7ToV8: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(\n schema,\n )}.\"desires\" DROP CONSTRAINT fk_desires_client`;\n },\n };\n\n const migrateV8ToV9: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD \"clientSchema\" JSONB`;\n },\n };\n\n const migrateV9ToV10: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.queries ADD \"queryName\" TEXT`;\n await tx`ALTER TABLE ${tx(schema)}.queries ADD \"queryArgs\" JSONB`;\n await tx`ALTER TABLE ${tx(schema)}.queries ALTER COLUMN \"clientAST\" DROP NOT NULL`;\n },\n };\n\n const migrateV10ToV11: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`DROP INDEX IF EXISTS ${tx(schema)}.desires_expires_at`;\n await tx`ALTER TABLE ${tx(schema)}.desires DROP COLUMN \"expiresAt\"`;\n await tx`DROP INDEX IF EXISTS ${tx(schema)}.client_patch_version`;\n await tx`ALTER TABLE ${tx(schema)}.clients DROP COLUMN \"patchVersion\"`;\n await tx`ALTER TABLE ${tx(schema)}.clients DROP COLUMN \"deleted\"`;\n },\n };\n\n const migratedV11ToV12: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.queries ALTER COLUMN \"queryArgs\" TYPE JSON USING \"queryArgs\"::JSON`;\n },\n };\n\n const migratedV12ToV13: Migration = {\n migrateSchema: async (_, tx) => {\n await tx`ALTER TABLE ${tx(schema)}.instances ADD COLUMN \"ttlClock\" DOUBLE PRECISION NOT NULL DEFAULT 0`;\n },\n };\n\n const migratedV13ToV14: Migration = {\n migrateSchema: async (_, sql) => {\n await sql`\n CREATE INDEX instances_last_active ON ${sql(schema)}.instances (\"lastActive\");\n `;\n\n // Update / add foreign key constraints to cascade deletes.\n for (const [table, reference] of [\n ['clients', 'instances'],\n ['queries', 'instances'],\n ['rows', 'rowsVersion'],\n ] as [string, string][]) {\n const constraint = sql(`fk_${table}_client_group`);\n await sql`\n ALTER TABLE ${sql(schema)}.${sql(table)} DROP CONSTRAINT IF EXISTS ${constraint}`;\n await sql`\n ALTER TABLE ${sql(schema)}.${sql(table)} ADD CONSTRAINT ${constraint}\n FOREIGN KEY(\"clientGroupID\")\n REFERENCES ${sql(schema)}.${sql(reference)} (\"clientGroupID\")\n ON DELETE CASCADE;\n `;\n }\n },\n };\n\n const migratedV14ToV15: Migration = {\n migrateSchema: async (_, sql) => {\n // Add new columns for storing inactivatedAt and ttl in milliseconds.\n // This avoids postgres.js type conversion issues with TIMESTAMPTZ and INTERVAL.\n await sql`ALTER TABLE ${sql(schema)}.desires \n ADD COLUMN \"inactivatedAtMs\" DOUBLE PRECISION`;\n await sql`ALTER TABLE ${sql(schema)}.desires \n ADD COLUMN \"ttlMs\" DOUBLE PRECISION`;\n },\n // Migrate existing data: convert TIMESTAMPTZ to milliseconds for inactivatedAt\n // and INTERVAL to milliseconds for ttl\n // Note: EXTRACT(EPOCH FROM NULL) returns NULL, so NULL values are preserved\n migrateData: async (lc, sql) => {\n lc.info?.(\n 'Migrating desires.inactivatedAt to inactivatedAtMs and ttl to ttlMs',\n );\n await sql`\n UPDATE ${sql(schema)}.desires\n SET \"inactivatedAtMs\" = EXTRACT(EPOCH FROM \"inactivatedAt\") * 1000,\n \"ttlMs\" = EXTRACT(EPOCH FROM \"ttl\") * 1000\n `;\n },\n };\n\n const migratedV15ToV16: Migration = {\n migrateSchema: async (_, sql) => {\n await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN \"profileID\" TEXT`;\n await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN \"deleted\" BOOL DEFAULT FALSE`;\n\n // Recreate the instances_last_active index to exclude tombstones\n await sql`\n DROP INDEX IF EXISTS ${sql(schema)}.instances_last_active`;\n await sql`\n CREATE INDEX instances_last_active ON ${sql(schema)}.instances (\"lastActive\")\n WHERE NOT \"deleted\"`;\n await sql`\n CREATE INDEX tombstones_last_active ON ${sql(schema)}.instances (\"lastActive\")\n WHERE \"deleted\"`;\n await sql`\n CREATE INDEX profile_ids_last_active ON ${sql(schema)}.instances (\"lastActive\", \"profileID\")\n WHERE \"profileID\" IS NOT NULL`;\n },\n\n // Backfill profileIDs to the `cg${clientGroupID}`, as is done for\n // client groups from old zero-clients that don't send a profileID.\n migrateData: async (lc, sql) => {\n lc.info?.('Backfilling instance.profileIDs');\n await sql`\n UPDATE ${sql(schema)}.instances\n SET \"profileID\" = 'cg' || \"clientGroupID\"\n WHERE \"profileID\" IS NULL\n `;\n },\n };\n\n const migratedV16ToV17: Migration = {\n migrateSchema: async (_, sql) => {\n await sql`ALTER TABLE ${sql(schema)}.queries ADD COLUMN \"rowSetSignature\" TEXT`;\n },\n };\n\n const migratedV17ToV18: Migration = {\n migrateSchema: async (_, sql) => {\n await sql`ALTER TABLE ${sql(schema)}.instances ADD COLUMN \"pinnedUser\" JSONB`;\n },\n };\n\n const schemaVersionMigrationMap: IncrementalMigrationMap = {\n 2: migrateV1toV2,\n 3: migrateV2ToV3,\n 4: migrateV3ToV4,\n // v5 enables asynchronous row-record flushing, and thus relies on\n // the logic that updates and checks the rowsVersion table in v3.\n 5: {minSafeVersion: 3},\n 6: migrateV5ToV6,\n 7: migrateV6ToV7,\n 8: migrateV7ToV8,\n 9: migrateV8ToV9,\n // v10 adds queryName and queryArgs to the queries table to support\n // custom queries. clientAST is now optional to support migrating\n // off client queries.\n 10: migrateV9ToV10,\n // V11 removes the deprecated queries.\"expiresAt\", clients.\"patchVersion\",\n // clients.\"deleted\" columns.\n 11: migrateV10ToV11,\n 12: migratedV11ToV12,\n // V13 adds instances.\"ttlClock\"\n 13: migratedV12ToV13,\n // V14 adds an index on instances.\"lastActive\" and a FK constraint\n // from rows.\"clientGroupID\" to rowsVersion.\"clientGroupID\" for\n // garbage collection\n 14: migratedV13ToV14,\n // V15 adds desires.\"inactivatedAtTTLClock\" to store TTLClock values\n // directly as DOUBLE PRECISION, avoiding postgres.js TIMESTAMPTZ\n // type conversion issues\n 15: migratedV14ToV15,\n // V16 adds instances.\"profileID\" and a corresponding index for estimating\n // active user counts more accurately for apps that use memstore.\n 16: migratedV15ToV16,\n // V17 adds queries.\"rowSetSignature\" — XOR'd hash of row IDs attached to\n // each query, used to detect drift on re-hydration of queries containing\n // the Cap operator.\n 17: migratedV16ToV17,\n // V18 adds instances.\"pinnedUser\", the user of the client group's first\n // validated connection, so that the group stays pinned to that user\n // across view-syncer restarts. NULL for existing groups until their next\n // validated connection.\n 18: migratedV17ToV18,\n };\n\n await runSchemaMigrations(\n log,\n 'view-syncer',\n cvrSchema(shard),\n db,\n setupMigration,\n schemaVersionMigrationMap,\n );\n}\n"],"mappings":"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"}
@@ -6,11 +6,11 @@ import { Database } from "../../../../zqlite/src/db.js";
6
6
  import { recordIndexUsage } from "../../../../zqlite/src/index-usage.js";
7
7
  import { fromSQLiteTypes } from "../../../../zqlite/src/table-source.js";
8
8
  import "../replicator/schema/constants.js";
9
+ import { id } from "../../types/sql.js";
9
10
  import { normalizedKeyOrder } from "../../types/row-key.js";
10
11
  import { changeLogEntrySchema } from "../replicator/schema/change-log.js";
11
12
  import { getReplicationState } from "../replicator/schema/replication-state.js";
12
13
  import { StatementRunner } from "../../db/statements.js";
13
- import { id } from "../../types/sql.js";
14
14
  //#region ../zero-cache/src/services/view-syncer/snapshotter.ts
15
15
  /**
16
16
  * A `Snapshotter` manages the progression of database snapshots for a
@@ -1 +1 @@
1
- {"version":3,"file":"view-syncer.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/view-syncer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view-syncer.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/view-syncer.ts"],"names":[],"mappings":"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"}