@rocicorp/zero 1.12.0-canary.12 → 1.12.0-canary.13

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 (211) hide show
  1. package/out/replicache/src/btree/diff.d.ts.map +1 -1
  2. package/out/replicache/src/btree/diff.js +1 -2
  3. package/out/replicache/src/btree/diff.js.map +1 -1
  4. package/out/replicache/src/btree/read.d.ts +31 -1
  5. package/out/replicache/src/btree/read.d.ts.map +1 -1
  6. package/out/replicache/src/btree/read.js +74 -19
  7. package/out/replicache/src/btree/read.js.map +1 -1
  8. package/out/replicache/src/btree/splice.d.ts.map +1 -1
  9. package/out/replicache/src/btree/splice.js +2 -1
  10. package/out/replicache/src/btree/splice.js.map +1 -1
  11. package/out/replicache/src/btree/write.d.ts.map +1 -1
  12. package/out/replicache/src/btree/write.js +2 -1
  13. package/out/replicache/src/btree/write.js.map +1 -1
  14. package/out/replicache/src/persist/collect-idb-databases.d.ts +1 -0
  15. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  16. package/out/replicache/src/persist/collect-idb-databases.js +13 -5
  17. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  18. package/out/replicache/src/scan-iterator.js +1 -1
  19. package/out/replicache/src/sync/request-id.js +2 -2
  20. package/out/replicache/src/sync/request-id.js.map +1 -1
  21. package/out/shared/src/bigint-json.d.ts.map +1 -1
  22. package/out/shared/src/bigint-json.js +1 -0
  23. package/out/shared/src/bigint-json.js.map +1 -1
  24. package/out/shared/src/btree-set.d.ts +21 -0
  25. package/out/shared/src/btree-set.d.ts.map +1 -1
  26. package/out/shared/src/btree-set.js +54 -0
  27. package/out/shared/src/btree-set.js.map +1 -1
  28. package/out/shared/src/headers.js +20 -0
  29. package/out/shared/src/headers.js.map +1 -0
  30. package/out/shared/src/natural-runs.d.ts +191 -0
  31. package/out/shared/src/natural-runs.d.ts.map +1 -0
  32. package/out/shared/src/natural-runs.js +337 -0
  33. package/out/shared/src/natural-runs.js.map +1 -0
  34. package/out/shared/src/random-uint64.d.ts.map +1 -1
  35. package/out/shared/src/random-uint64.js +2 -2
  36. package/out/shared/src/random-uint64.js.map +1 -1
  37. package/out/shared/src/random-values.d.ts +19 -1
  38. package/out/shared/src/random-values.d.ts.map +1 -1
  39. package/out/shared/src/random-values.js +38 -4
  40. package/out/shared/src/random-values.js.map +1 -1
  41. package/out/shared/src/tuple-map.d.ts +22 -0
  42. package/out/shared/src/tuple-map.d.ts.map +1 -0
  43. package/out/shared/src/tuple-map.js +48 -0
  44. package/out/shared/src/tuple-map.js.map +1 -0
  45. package/out/zero/package.js +1 -1
  46. package/out/zero/package.js.map +1 -1
  47. package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
  48. package/out/zero-cache/src/auth/auth.js +5 -0
  49. package/out/zero-cache/src/auth/auth.js.map +1 -1
  50. package/out/zero-cache/src/config/zero-config.d.ts +21 -0
  51. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  52. package/out/zero-cache/src/config/zero-config.js +47 -9
  53. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  54. package/out/zero-cache/src/custom-queries/transform-query.js +2 -2
  55. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  56. package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
  57. package/out/zero-cache/src/db/pg-to-lite.js +3 -2
  58. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  59. package/out/zero-cache/src/db/pg-type-parser.js +55 -2
  60. package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
  61. package/out/zero-cache/src/server/change-streamer.js +5 -2
  62. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  63. package/out/zero-cache/src/server/inspector-delegate.js +6 -29
  64. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  65. package/out/zero-cache/src/server/main.js +5 -0
  66. package/out/zero-cache/src/server/main.js.map +1 -1
  67. package/out/zero-cache/src/server/replicator.js +3 -2
  68. package/out/zero-cache/src/server/replicator.js.map +1 -1
  69. package/out/zero-cache/src/server/syncer.js +5 -4
  70. package/out/zero-cache/src/server/syncer.js.map +1 -1
  71. package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
  72. package/out/zero-cache/src/server/worker-dispatcher.js +2 -1
  73. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  74. package/out/zero-cache/src/services/admin-auth.d.ts +22 -0
  75. package/out/zero-cache/src/services/admin-auth.d.ts.map +1 -0
  76. package/out/zero-cache/src/services/admin-auth.js +42 -0
  77. package/out/zero-cache/src/services/admin-auth.js.map +1 -0
  78. package/out/zero-cache/src/services/auth-attempt-counter.d.ts +33 -0
  79. package/out/zero-cache/src/services/auth-attempt-counter.d.ts.map +1 -0
  80. package/out/zero-cache/src/services/auth-attempt-counter.js +61 -0
  81. package/out/zero-cache/src/services/auth-attempt-counter.js.map +1 -0
  82. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +1 -1
  83. package/out/zero-cache/src/services/change-source/pg/change-source.js +110 -13
  84. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  85. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +13 -7
  86. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  87. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +38 -5
  88. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  89. package/out/zero-cache/src/services/change-source/pg/schema/init.js +10 -1
  90. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  91. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +4 -0
  92. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  93. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +10 -3
  94. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  95. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +23 -2
  96. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  97. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +2 -2
  98. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  99. package/out/zero-cache/src/services/change-streamer/change-streamer.js +10 -3
  100. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  101. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  102. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  103. package/out/zero-cache/src/services/heapz.js +4 -5
  104. package/out/zero-cache/src/services/heapz.js.map +1 -1
  105. package/out/zero-cache/src/services/mutagen/error.d.ts +5 -0
  106. package/out/zero-cache/src/services/mutagen/error.d.ts.map +1 -1
  107. package/out/zero-cache/src/services/mutagen/error.js +7 -1
  108. package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
  109. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
  110. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  111. package/out/zero-cache/src/services/mutagen/pusher.js +1 -1
  112. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  113. package/out/zero-cache/src/services/plannerz.d.ts.map +1 -1
  114. package/out/zero-cache/src/services/plannerz.js +3 -7
  115. package/out/zero-cache/src/services/plannerz.js.map +1 -1
  116. package/out/zero-cache/src/services/profz.d.ts.map +1 -1
  117. package/out/zero-cache/src/services/profz.js +4 -13
  118. package/out/zero-cache/src/services/profz.js.map +1 -1
  119. package/out/zero-cache/src/services/replicator/change-processor.js +29 -2
  120. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  121. package/out/zero-cache/src/services/replicator/incremental-sync.js +3 -3
  122. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  123. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  124. package/out/zero-cache/src/services/statz.js +2 -7
  125. package/out/zero-cache/src/services/statz.js.map +1 -1
  126. package/out/zero-cache/src/services/view-syncer/client-handler.js +22 -1
  127. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  128. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +40 -2
  129. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  130. package/out/zero-cache/src/services/view-syncer/cvr-store.js +54 -17
  131. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  132. package/out/zero-cache/src/services/view-syncer/cvr.js +11 -0
  133. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  134. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js +107 -0
  135. package/out/zero-cache/src/services/view-syncer/inspect-auth-limiter.js.map +1 -0
  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.js +2 -1
  139. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  140. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +16 -14
  141. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  142. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +4 -1
  143. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  144. package/out/zero-cache/src/services/view-syncer/schema/init.js +3 -0
  145. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  146. package/out/zero-cache/src/services/view-syncer/view-syncer.js +89 -51
  147. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  148. package/out/zero-cache/src/types/client-group-log-id.d.ts +9 -0
  149. package/out/zero-cache/src/types/client-group-log-id.d.ts.map +1 -0
  150. package/out/zero-cache/src/types/client-group-log-id.js +16 -0
  151. package/out/zero-cache/src/types/client-group-log-id.js.map +1 -0
  152. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  153. package/out/zero-cache/src/types/lite.js +1 -0
  154. package/out/zero-cache/src/types/lite.js.map +1 -1
  155. package/out/zero-cache/src/types/pg.d.ts +13 -2
  156. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  157. package/out/zero-cache/src/types/pg.js +2 -2
  158. package/out/zero-cache/src/types/pg.js.map +1 -1
  159. package/out/zero-cache/src/types/poke-chunk.d.ts +25 -4
  160. package/out/zero-cache/src/types/poke-chunk.d.ts.map +1 -1
  161. package/out/zero-cache/src/types/poke-chunk.js +46 -5
  162. package/out/zero-cache/src/types/poke-chunk.js.map +1 -1
  163. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  164. package/out/zero-cache/src/workers/connection.js +10 -3
  165. package/out/zero-cache/src/workers/connection.js.map +1 -1
  166. package/out/zero-cache/src/workers/rehome.d.ts +10 -0
  167. package/out/zero-cache/src/workers/rehome.d.ts.map +1 -1
  168. package/out/zero-cache/src/workers/rehome.js +4 -2
  169. package/out/zero-cache/src/workers/rehome.js.map +1 -1
  170. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +3 -2
  171. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  172. package/out/zero-cache/src/workers/syncer.js +15 -15
  173. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  174. package/out/zero-client/src/client/inspector/inspector.d.ts +4 -0
  175. package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
  176. package/out/zero-client/src/client/inspector/inspector.js +4 -0
  177. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  178. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +10 -2
  179. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  180. package/out/zero-client/src/client/inspector/lazy-inspector.js +38 -31
  181. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  182. package/out/zero-client/src/client/inspector/query.d.ts +2 -2
  183. package/out/zero-client/src/client/inspector/query.d.ts.map +1 -1
  184. package/out/zero-client/src/client/inspector/query.js +4 -4
  185. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  186. package/out/zero-client/src/client/ivm-branch.d.ts +3 -0
  187. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  188. package/out/zero-client/src/client/ivm-branch.js +10 -5
  189. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  190. package/out/zero-client/src/client/reconnect-backoff.d.ts +31 -0
  191. package/out/zero-client/src/client/reconnect-backoff.d.ts.map +1 -0
  192. package/out/zero-client/src/client/reconnect-backoff.js +44 -0
  193. package/out/zero-client/src/client/reconnect-backoff.js.map +1 -0
  194. package/out/zero-client/src/client/version.js +1 -1
  195. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  196. package/out/zero-client/src/client/zero.js +7 -0
  197. package/out/zero-client/src/client/zero.js.map +1 -1
  198. package/out/zero-client/src/util/nanoid.js +2 -2
  199. package/out/zero-client/src/util/nanoid.js.map +1 -1
  200. package/out/zero-protocol/src/up.d.ts +42 -42
  201. package/out/zero-server/src/process-mutations.d.ts +10 -0
  202. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  203. package/out/zero-server/src/process-mutations.js +39 -6
  204. package/out/zero-server/src/process-mutations.js.map +1 -1
  205. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  206. package/out/zql/src/ivm/memory-source.js +89 -6
  207. package/out/zql/src/ivm/memory-source.js.map +1 -1
  208. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  209. package/out/zql/src/planner/planner-connection.js +37 -3
  210. package/out/zql/src/planner/planner-connection.js.map +1 -1
  211. package/package.json +1 -1
@@ -28,6 +28,7 @@ import "./initial-sync.js";
28
28
  import { streamBackfill } from "./backfill-stream.js";
29
29
  import { ReplicationSlotCleanupMonitor } from "./replication-slot-cleanup-monitor.js";
30
30
  import { registerReplicationSlotHealthMetrics } from "./replication-slot-health.js";
31
+ import { timingSafeEqual } from "node:crypto";
31
32
  import { nanoid } from "nanoid";
32
33
  import postgres from "postgres";
33
34
  import { PG_ADMIN_SHUTDOWN, PG_INSUFFICIENT_PRIVILEGE } from "@drdgvhbh/postgres-error-codes";
@@ -123,7 +124,8 @@ var PostgresChangeSource = class {
123
124
  */
124
125
  const isTransactionalMessage = (lsn, msg) => {
125
126
  if (msg.tag === "message" && msg.prefix === this.#lagReporter?.messagePrefix) {
126
- changes.pushStatus(this.#lagReporter.processLagReportMessage(msg, lsn));
127
+ const status = this.#lagReporter.processLagReportMessage(msg, lsn);
128
+ if (status) changes.pushStatus(status);
127
129
  return false;
128
130
  }
129
131
  const status = this.#lagReporter?.checkCurrentLSN(lsn);
@@ -363,6 +365,10 @@ var LagReporter = class LagReporter {
363
365
  description: "Number of replication lag reports retried because the expected report was not received before the next report interval.",
364
366
  unit: "{report}"
365
367
  });
368
+ #lagReportsIgnored = getOrCreateCounter("replication", "lag_reports_ignored", {
369
+ description: "Number of messages with the lag report prefix ignored because their content could not be parsed as a lag report.",
370
+ unit: "{message}"
371
+ });
366
372
  #pgVersion;
367
373
  #expectingLagReport = null;
368
374
  #lastAcceptedSendTimeMs = 0;
@@ -532,10 +538,22 @@ var LagReporter = class LagReporter {
532
538
  * XLogData header), rather than the `messageLsn` of the message itself,
533
539
  * which is not guaranteed to be comparable to other stream LSNs (e.g. on
534
540
  * Aurora). See {@link initiateLagReport}.
541
+ * @returns the status to send downstream, or `undefined` if the message is
542
+ * not a lag report. Any session that can call
543
+ * `pg_logical_emit_message()` can emit a message with the lag report
544
+ * prefix; one that cannot be parsed carries no report and is ignored,
545
+ * as a message of an unknown prefix would be, rather than failing the
546
+ * stream (which would replay it from the same position).
535
547
  */
536
548
  processLagReportMessage(msg, lsn) {
537
549
  assert(msg.prefix === this.messagePrefix, `unexpected message prefix: ${msg.prefix}`);
538
- const report = parseLogicalMessageContent(this.#lc, msg, lagReportSchema);
550
+ let report;
551
+ try {
552
+ report = parseLogicalMessageContent(this.#lc, msg, lagReportSchema);
553
+ } catch {
554
+ this.#lagReportsIgnored.add(1);
555
+ return;
556
+ }
539
557
  return this.#processLagReport(report, majorVersionToString(lsn));
540
558
  }
541
559
  #processLagReport(report, watermark) {
@@ -700,9 +718,50 @@ var ChangeMaker = class {
700
718
  default: throw new Error(`Unexpected message type ${stringify(msg)}`);
701
719
  }
702
720
  }
721
+ /**
722
+ * Any session that can call `pg_logical_emit_message()` can emit a message
723
+ * with the shard's ddl prefix. Only events that carry the shard's secret,
724
+ * which the upstream functions read from a table in the shard's schema
725
+ * (see `createEventFunctionStatements()`), are applied. Events emitted
726
+ * before the secret was installed (by functions that predate it) are
727
+ * accepted without one.
728
+ *
729
+ * @returns why the event cannot be verified, or `undefined` if it can.
730
+ */
731
+ #ddlEventOriginProblem(lsn, json, ddlSecret, ddlSecretLsn) {
732
+ const secret = field(json, "secret");
733
+ if (typeof secret === "string") {
734
+ if (equalSecrets(secret, ddlSecret)) return;
735
+ } else if ((secret === void 0 || secret === null) && ddlSecretLsn && lsn <= toBigInt(ddlSecretLsn)) return;
736
+ return `the event does not carry the secret of the ${upstreamSchema(this.#shard)} schema's event functions (secret ${typeof secret === "string" ? "mismatch" : "absent"}, installed at ${ddlSecretLsn ?? "unknown"})`;
737
+ }
703
738
  #lastReplicationEvent;
739
+ #ddlEventsIgnored = getOrCreateCounter("replication", "ddl_events_ignored", {
740
+ description: "Number of ddl messages ignored because they were not emitted by the shard's upstream functions (missing or wrong secret, or not valid JSON).",
741
+ unit: "{message}"
742
+ });
704
743
  #handleDdlMessage(lc, lsn, msg) {
705
- const event = parseLogicalMessageContent(lc, msg, replicationEventSchema);
744
+ const { ddlSecret, ddlSecretLsn } = this.#shardConfig;
745
+ assert(ddlSecret, "shard config has no ddl event secret");
746
+ const content = decodeLogicalMessage(msg);
747
+ let json;
748
+ let problem;
749
+ try {
750
+ json = JSON.parse(content);
751
+ } catch (e) {
752
+ problem = `not valid JSON: ${String(e)}`;
753
+ }
754
+ problem ??= this.#ddlEventOriginProblem(lsn, json, ddlSecret, ddlSecretLsn);
755
+ if (problem !== void 0) {
756
+ this.#ddlEventsIgnored.add(1);
757
+ lc.warn?.(`ignoring ${msg.prefix} message at ${fromBigInt(lsn)} (not emitted by the shard's upstream functions; replication continues): ${problem}`, describeUnverifiedMessage(json));
758
+ lc.debug?.(`ignored ${msg.prefix} message content`, { content: content.substring(0, 4096) });
759
+ return [];
760
+ }
761
+ const event = validateLogicalMessage(lc, msg, json, replicationEventSchema, () => stringify(field(json, "secret") === void 0 ? json : {
762
+ ...json,
763
+ secret: "<redacted>"
764
+ }));
706
765
  lc = lc.withContext("lsn", fromBigInt(lsn)).withContext("tag", event.event.tag).withContext("query", event.context.query);
707
766
  if (event.previousSchema) warnForSkippedIndexes(lc, event.previousSchema, this.#skippedIndexWarnings);
708
767
  if (event.schema) warnForSkippedIndexes(lc, event.schema, this.#skippedIndexWarnings);
@@ -1056,8 +1115,7 @@ function summarizeSchemaForLog(schema) {
1056
1115
  };
1057
1116
  }
1058
1117
  function summarizeReplicationEventForLog(event) {
1059
- const { schema, ...rest } = event;
1060
- const { previousSchema, ...eventWithoutSchemas } = rest;
1118
+ const { schema, previousSchema, secret: _, ...eventWithoutSchemas } = event;
1061
1119
  return {
1062
1120
  ...eventWithoutSchemas,
1063
1121
  ...schema !== void 0 && { schema: summarizeSchemaForLog(schema) },
@@ -1086,20 +1144,59 @@ var ShutdownSignal = class extends AbortError {
1086
1144
  super("shutdown signal received (e.g. another zero-cache taking over the replication stream)", { cause });
1087
1145
  }
1088
1146
  };
1147
+ function decodeLogicalMessage({ content }) {
1148
+ return content instanceof Buffer ? content.toString("utf-8") : new TextDecoder().decode(content);
1149
+ }
1089
1150
  function parseLogicalMessageContent(lc, msg, schema) {
1090
- const { content } = msg;
1091
- const str = content instanceof Buffer ? content.toString("utf-8") : new TextDecoder().decode(content);
1151
+ const str = decodeLogicalMessage(msg);
1152
+ let json;
1153
+ try {
1154
+ json = JSON.parse(str);
1155
+ } catch (e) {
1156
+ return failParse(lc, msg, e, str);
1157
+ }
1158
+ return validateLogicalMessage(lc, msg, json, schema, () => str);
1159
+ }
1160
+ function validateLogicalMessage(lc, msg, json, schema, contentForLog) {
1092
1161
  try {
1093
- const json = JSON.parse(str);
1094
1162
  return parse(json, schema, "passthrough");
1095
1163
  } catch (e) {
1096
- lc.error?.(`unable to parse logical message content: ${String(e)}`, { message: {
1097
- ...msg,
1098
- content: str
1099
- } });
1100
- throw e;
1164
+ return failParse(lc, msg, e, contentForLog());
1101
1165
  }
1102
1166
  }
1167
+ /**
1168
+ * Logs and rethrows a parse failure. Any session that can call
1169
+ * `pg_logical_emit_message()` can emit a message with a prefix that the
1170
+ * zero-cache parses, so the content is untrusted: it is logged at `warn`
1171
+ * (callers skip the message, so there is nothing for an operator to fix in
1172
+ * zero-cache) without the content, which goes to `debug`, bounded.
1173
+ */
1174
+ function failParse(lc, msg, e, content) {
1175
+ const { content: _, ...header } = msg;
1176
+ lc.warn?.(`unable to parse logical message content: ${String(e)}`, {
1177
+ message: header,
1178
+ contentLength: content.length
1179
+ });
1180
+ lc.debug?.(`unparseable logical message content`, { content: content.substring(0, 4096) });
1181
+ throw e;
1182
+ }
1183
+ /** A property of untrusted JSON, or `undefined` if there is no such property. */
1184
+ function field(json, name) {
1185
+ return typeof json === "object" && json !== null && name in json ? json[name] : void 0;
1186
+ }
1187
+ function describeUnverifiedMessage(json) {
1188
+ const str = (value) => typeof value === "string" ? value.substring(0, 200) : null;
1189
+ return {
1190
+ type: str(field(json, "type")),
1191
+ tag: str(field(field(json, "event"), "tag")),
1192
+ query: str(field(field(json, "context"), "query"))
1193
+ };
1194
+ }
1195
+ function equalSecrets(a, b) {
1196
+ const bufA = Buffer.from(a);
1197
+ const bufB = Buffer.from(b);
1198
+ return bufA.length === bufB.length && timingSafeEqual(bufA, bufB);
1199
+ }
1103
1200
  //#endregion
1104
1201
  export { Acker, LagReporter, PostgresChangeSource, isIndexStructurallyChanged };
1105
1202