@rocicorp/zero 1.8.0 → 1.9.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/out/shared/src/cache.d.ts +8 -1
  2. package/out/shared/src/cache.d.ts.map +1 -1
  3. package/out/shared/src/cache.js +25 -9
  4. package/out/shared/src/cache.js.map +1 -1
  5. package/out/shared/src/objects.d.ts +6 -1
  6. package/out/shared/src/objects.d.ts.map +1 -1
  7. package/out/shared/src/objects.js +19 -4
  8. package/out/shared/src/objects.js.map +1 -1
  9. package/out/zero/package.js +2 -19
  10. package/out/zero/package.js.map +1 -1
  11. package/out/zero-cache/src/config/zero-config.d.ts +4 -0
  12. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  13. package/out/zero-cache/src/config/zero-config.js +21 -6
  14. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  15. package/out/zero-cache/src/custom-queries/transform-query.d.ts +6 -0
  16. package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
  17. package/out/zero-cache/src/custom-queries/transform-query.js +8 -0
  18. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  19. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  20. package/out/zero-cache/src/db/migration-lite.js +5 -2
  21. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  22. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  23. package/out/zero-cache/src/db/migration.js +3 -1
  24. package/out/zero-cache/src/db/migration.js.map +1 -1
  25. package/out/zero-cache/src/db/sqlite-corruption.d.ts +11 -0
  26. package/out/zero-cache/src/db/sqlite-corruption.d.ts.map +1 -0
  27. package/out/zero-cache/src/db/sqlite-corruption.js +191 -0
  28. package/out/zero-cache/src/db/sqlite-corruption.js.map +1 -0
  29. package/out/zero-cache/src/server/anonymous-otel-start.d.ts +1 -1
  30. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  31. package/out/zero-cache/src/server/backup-watermark-reader.js +1 -1
  32. package/out/zero-cache/src/server/backup-watermark-reader.js.map +1 -1
  33. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  34. package/out/zero-cache/src/server/change-streamer.js +7 -2
  35. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  36. package/out/zero-cache/src/server/logging.d.ts +8 -0
  37. package/out/zero-cache/src/server/logging.d.ts.map +1 -1
  38. package/out/zero-cache/src/server/logging.js +27 -5
  39. package/out/zero-cache/src/server/logging.js.map +1 -1
  40. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  41. package/out/zero-cache/src/server/main.js +6 -1
  42. package/out/zero-cache/src/server/main.js.map +1 -1
  43. package/out/zero-cache/src/server/mutator.js +1 -1
  44. package/out/zero-cache/src/server/mutator.js.map +1 -1
  45. package/out/zero-cache/src/server/otel-log-sink.d.ts +7 -1
  46. package/out/zero-cache/src/server/otel-log-sink.d.ts.map +1 -1
  47. package/out/zero-cache/src/server/otel-log-sink.js +7 -2
  48. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  49. package/out/zero-cache/src/server/reaper.js +1 -1
  50. package/out/zero-cache/src/server/reaper.js.map +1 -1
  51. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  52. package/out/zero-cache/src/server/replicator.js +11 -1
  53. package/out/zero-cache/src/server/replicator.js.map +1 -1
  54. package/out/zero-cache/src/server/shadow-syncer.js +1 -1
  55. package/out/zero-cache/src/server/shadow-syncer.js.map +1 -1
  56. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  57. package/out/zero-cache/src/server/syncer.js +6 -1
  58. package/out/zero-cache/src/server/syncer.js.map +1 -1
  59. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  60. package/out/zero-cache/src/services/change-source/common/replica-schema.js +8 -5
  61. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  62. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +36 -2
  63. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  64. package/out/zero-cache/src/services/change-source/pg/change-source.js +76 -33
  65. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  66. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +15 -0
  67. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  68. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +41 -10
  69. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  70. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +21 -0
  71. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  72. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +34 -5
  73. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  74. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +2 -2
  75. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  76. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  77. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +61 -87
  78. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  79. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +17 -12
  80. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  81. package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
  82. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  83. package/out/zero-cache/src/services/life-cycle.js +15 -3
  84. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  85. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  86. package/out/zero-cache/src/services/litestream/commands.js +20 -3
  87. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  88. package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js +2 -2
  89. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  90. package/out/zero-cache/src/services/mutagen/mutagen.js +4 -1
  91. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  92. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  93. package/out/zero-cache/src/services/replicator/change-processor.js +28 -15
  94. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  95. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +1 -1
  96. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/replicator/reporter/recorder.js +5 -12
  98. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  99. package/out/zero-cache/src/services/replicator/write-worker.js +38 -7
  100. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  101. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  102. package/out/zero-cache/src/services/view-syncer/cvr.js +8 -1
  103. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  104. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  105. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +66 -26
  106. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  107. package/out/zero-cache/src/services/view-syncer/query-covering.d.ts +28 -0
  108. package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -0
  109. package/out/zero-cache/src/services/view-syncer/query-covering.js +159 -0
  110. package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -0
  111. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +2 -0
  112. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  113. package/out/zero-cache/src/services/view-syncer/view-syncer.js +71 -1
  114. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  115. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  116. package/out/zero-cache/src/types/lite.js +4 -1
  117. package/out/zero-cache/src/types/lite.js.map +1 -1
  118. package/out/zero-cache/src/types/pg.d.ts +18 -0
  119. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  120. package/out/zero-cache/src/types/pg.js +50 -0
  121. package/out/zero-cache/src/types/pg.js.map +1 -1
  122. package/out/zero-cache/src/workers/syncer.d.ts +1 -1
  123. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  124. package/out/zero-cache/src/workers/syncer.js +1 -0
  125. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  126. package/out/zero-client/src/client/crud.d.ts.map +1 -1
  127. package/out/zero-client/src/client/crud.js +3 -4
  128. package/out/zero-client/src/client/crud.js.map +1 -1
  129. package/out/zero-client/src/client/version.js +1 -1
  130. package/out/zero-schema/src/builder/relationship-builder.d.ts.map +1 -1
  131. package/out/zero-schema/src/builder/relationship-builder.js +3 -2
  132. package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
  133. package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
  134. package/out/zero-schema/src/builder/schema-builder.js +7 -7
  135. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  136. package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
  137. package/out/zero-schema/src/builder/table-builder.js +2 -1
  138. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  139. package/out/zero-server/src/custom.js +2 -1
  140. package/out/zero-server/src/custom.js.map +1 -1
  141. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  142. package/out/zql/src/ivm/view-apply-change.js +2 -1
  143. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  144. package/out/zql/src/mutate/crud.d.ts +10 -8
  145. package/out/zql/src/mutate/crud.d.ts.map +1 -1
  146. package/out/zql/src/mutate/crud.js +3 -4
  147. package/out/zql/src/mutate/crud.js.map +1 -1
  148. package/out/zqlite/src/db.js +2 -2
  149. package/out/zqlite/src/internal/statement-cache.d.ts +25 -1
  150. package/out/zqlite/src/internal/statement-cache.d.ts.map +1 -1
  151. package/out/zqlite/src/internal/statement-cache.js +48 -18
  152. package/out/zqlite/src/internal/statement-cache.js.map +1 -1
  153. package/out/zqlite/src/query-builder.js +3 -3
  154. package/out/zqlite/src/query-builder.js.map +1 -1
  155. package/out/zqlite/src/sqlite-cost-model.js +5 -5
  156. package/out/zqlite/src/table-source.js +3 -3
  157. package/package.json +2 -33
@@ -2,14 +2,16 @@ import type { LogContext } from '@rocicorp/logger';
2
2
  import * as v from '../../../../../shared/src/valita.ts';
3
3
  import type { PublishedTableSpec } from '../../../db/specs.ts';
4
4
  import { type LexiVersion } from '../../../types/lexi-version.ts';
5
- import { type ShardConfig } from '../../../types/shards.ts';
5
+ import { type PostgresDB } from '../../../types/pg.ts';
6
+ import { type ShardConfig, type ShardID } from '../../../types/shards.ts';
6
7
  import type { Sink } from '../../../types/streams.ts';
7
8
  import { type SubscriptionState } from '../../replicator/schema/replication-state.ts';
8
9
  import type { ChangeSource } from '../change-source.ts';
9
10
  import { type Listener } from '../common/change-stream-multiplexer.ts';
11
+ import type { DownstreamStatusMessage } from '../protocol/current.ts';
10
12
  import type { ChangeStreamMessage } from '../protocol/current/downstream.ts';
11
13
  import { type InitialSyncOptions, type ServerContext } from './initial-sync.ts';
12
- import type { MessageRelation as PostgresRelation } from './logical-replication/pgoutput.types.ts';
14
+ import type { MessageMessage, MessageRelation as PostgresRelation } from './logical-replication/pgoutput.types.ts';
13
15
  /**
14
16
  * Initializes a Postgres change source, including the initial sync of the
15
17
  * replica, before streaming changes from the corresponding logical replication
@@ -31,6 +33,38 @@ declare const lagReportSchema: v.ObjectType<{
31
33
  commitTimeMs: v.Type<number>;
32
34
  }, undefined>;
33
35
  export type LagReport = v.Infer<typeof lagReportSchema>;
36
+ export declare class LagReporter {
37
+ #private;
38
+ static readonly MESSAGE_SUFFIX = "/lag-report/v1";
39
+ readonly messagePrefix: string;
40
+ constructor(lc: LogContext, shard: ShardID, db: PostgresDB, lagIntervalMs: number);
41
+ get pgVersion(): number | undefined;
42
+ initiateLagReport(log?: boolean): Promise<{
43
+ nextSendTimeMs: number;
44
+ }>;
45
+ /**
46
+ * In Postgres < 17, the pg_logical_emit_message lacks an immediate "flush"
47
+ * option, which can cause messages to be missed when the replication stream
48
+ * starts up:
49
+ *
50
+ * ```
51
+ * * emit message → WAL write (buffered, not flushed)
52
+ * * walsender reads up to current flush LSN
53
+ * * emitted message's LSN is beyond flush LSN → not yet visible
54
+ * * stream feedback/acknowledgment advances slot
55
+ * * WAL eventually flushes → but slot has already moved past it
56
+ * ```
57
+ *
58
+ * This has been seen to happen for the initial `wal_writer_delay` interval
59
+ * of a replication session.
60
+ *
61
+ * To account for this, the last emitted lag report is considered "received"
62
+ * if the stream has advanced beyond the LSN of the report.
63
+ */
64
+ checkCurrentLSN(lsn: bigint): DownstreamStatusMessage | undefined;
65
+ stop(): void;
66
+ processLagReportMessage(msg: MessageMessage): DownstreamStatusMessage;
67
+ }
34
68
  export declare function relationDifferent(a: PublishedTableSpec, b: PostgresRelation): boolean;
35
69
  export {};
36
70
  //# sourceMappingURL=change-source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAcjD,OAAO,KAAK,CAAC,MAAM,qCAAqC,CAAC;AAMzD,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAC,KAAK,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAQhE,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,2BAA2B,CAAC;AAEpD,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAC,YAAY,EAAe,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAEL,KAAK,QAAQ,EACd,MAAM,wCAAwC,CAAC;AAchD,OAAO,KAAK,EAEV,mBAAmB,EAEpB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAGV,eAAe,IAAI,gBAAgB,EACpC,MAAM,yCAAyC,CAAC;AA0BjD;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,aAAa,EACtB,mBAAmB,SAAI,GACtB,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CAuC7E;AAuaD,qBAAa,KAAM,YAAW,QAAQ;;gBAIxB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAI9B,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAgC3C,GAAG,CAAC,SAAS,EAAE,WAAW;CAoB3B;AAED,QAAA,MAAM,eAAe;;;;aAInB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAqzBxD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,gBAAgB,WAwB3E"}
1
+ {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAcjD,OAAO,KAAK,CAAC,MAAM,qCAAqC,CAAC;AAMzD,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAC,KAAK,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAEhE,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,OAAO,EACb,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,2BAA2B,CAAC;AAEpD,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAC,YAAY,EAAe,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAEL,KAAK,QAAQ,EACd,MAAM,wCAAwC,CAAC;AAEhD,OAAO,KAAK,EAEV,uBAAuB,EAExB,MAAM,wBAAwB,CAAC;AAQhC,OAAO,KAAK,EAEV,mBAAmB,EAEpB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAEV,cAAc,EACd,eAAe,IAAI,gBAAgB,EACpC,MAAM,yCAAyC,CAAC;AA0BjD;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,aAAa,EACtB,mBAAmB,SAAI,GACtB,OAAO,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAC,CAAC,CAuC7E;AAuaD,qBAAa,KAAM,YAAW,QAAQ;;gBAIxB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAI9B,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAgC3C,GAAG,CAAC,SAAS,EAAE,WAAW;CAoB3B;AAED,QAAA,MAAM,eAAe;;;;aAInB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIxD,qBAAa,WAAW;;IACtB,MAAM,CAAC,QAAQ,CAAC,cAAc,oBAAoB;IAGlD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAqB7B,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,OAAO,EACd,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,MAAM;IAiBvB,IAAI,SAAS,uBAEZ;IAEK,iBAAiB,CAAC,GAAG,UAAQ;;;IA0EnC;;;;;;;;;;;;;;;;;;OAkBG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS;IAcjE,IAAI;IA2CJ,uBAAuB,CAAC,GAAG,EAAE,cAAc,GAAG,uBAAuB;CAiDtE;AAonBD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,gBAAgB,WAwB3E"}
@@ -9,6 +9,7 @@ import { stringify } from "../../../../../shared/src/bigint-json.js";
9
9
  import { upstreamSchema } from "../../../types/shards.js";
10
10
  import { Database } from "../../../../../zqlite/src/db.js";
11
11
  import { UnsupportedColumnDefaultError, mapPostgresToLiteColumn } from "../../../db/pg-to-lite.js";
12
+ import { getOrCreateCounter } from "../../../observability/metrics.js";
12
13
  import { getSubscriptionStateAndContext } from "../../replicator/schema/replication-state.js";
13
14
  import { StatementRunner } from "../../../db/statements.js";
14
15
  import { connectPgClient, isPostgresError, pgClient } from "../../../types/pg.js";
@@ -314,6 +315,10 @@ var LagReporter = class LagReporter {
314
315
  messagePrefix;
315
316
  #db;
316
317
  #lagIntervalMs;
318
+ #lagReportRetries = getOrCreateCounter("replication", "lag_report_retries", {
319
+ description: "Number of replication lag reports retried because the expected report was not received before the next report interval.",
320
+ unit: "{report}"
321
+ });
317
322
  #pgVersion;
318
323
  #expectingLagReport = null;
319
324
  #timer;
@@ -347,33 +352,39 @@ var LagReporter = class LagReporter {
347
352
  this.#expectingLagReport = lagReport;
348
353
  let commitTimeMs;
349
354
  let lsn;
350
- if (pgVersion >= 17e4) [{commitTimeMs, lsn}] = await this.#db`
351
- WITH CTE AS (SELECT extract(epoch from now()) * 1000 AS "commitTimeMs")
352
- SELECT "commitTimeMs", pg_logical_emit_message(
353
- false,
354
- ${this.messagePrefix},
355
- json_build_object(
356
- 'id', ${id}::text,
357
- 'sendTimeMs', ${now}::int8,
358
- 'commitTimeMs', "commitTimeMs"
359
- )::text,
360
- true
361
- ) as lsn FROM CTE;
362
- `;
363
- else [{commitTimeMs, lsn}] = await this.#db`
364
- WITH CTE AS (SELECT extract(epoch from now()) * 1000 as "commitTimeMs")
365
- SELECT "commitTimeMs", pg_logical_emit_message(
366
- false,
367
- ${this.messagePrefix},
368
- json_build_object(
369
- 'id', ${id}::text,
370
- 'sendTimeMs', ${now}::int8,
371
- 'commitTimeMs', "commitTimeMs"
372
- )::text
373
- ) as lsn FROM CTE;
374
- `;
355
+ try {
356
+ if (pgVersion >= 17e4) [{commitTimeMs, lsn}] = await this.#db`
357
+ WITH CTE AS (SELECT extract(epoch from now()) * 1000 AS "commitTimeMs")
358
+ SELECT "commitTimeMs", pg_logical_emit_message(
359
+ false,
360
+ ${this.messagePrefix},
361
+ json_build_object(
362
+ 'id', ${id}::text,
363
+ 'sendTimeMs', ${now}::int8,
364
+ 'commitTimeMs', "commitTimeMs"
365
+ )::text,
366
+ true
367
+ ) as lsn FROM CTE;
368
+ `;
369
+ else [{commitTimeMs, lsn}] = await this.#db`
370
+ WITH CTE AS (SELECT extract(epoch from now()) * 1000 as "commitTimeMs")
371
+ SELECT "commitTimeMs", pg_logical_emit_message(
372
+ false,
373
+ ${this.messagePrefix},
374
+ json_build_object(
375
+ 'id', ${id}::text,
376
+ 'sendTimeMs', ${now}::int8,
377
+ 'commitTimeMs', "commitTimeMs"
378
+ )::text
379
+ ) as lsn FROM CTE;
380
+ `;
381
+ } catch (e) {
382
+ if (this.#expectingLagReport?.id === id) this.#expectingLagReport = null;
383
+ throw e;
384
+ }
375
385
  lagReport.lsn = toBigInt(lsn);
376
386
  lagReport.commitTimeMs = commitTimeMs;
387
+ if (this.#expectingLagReport?.id === id) this.#scheduleMissingReportRetry(id);
377
388
  if (log) this.#lc.info?.(`initiated lag report at lsn ${lsn}`, {
378
389
  id,
379
390
  lsn,
@@ -415,6 +426,7 @@ var LagReporter = class LagReporter {
415
426
  this.#expectingLagReport = null;
416
427
  clearTimeout(this.#timer);
417
428
  this.#timer = setTimeout(async () => {
429
+ this.#timer = void 0;
418
430
  try {
419
431
  await this.initiateLagReport();
420
432
  } catch (e) {
@@ -423,6 +435,26 @@ var LagReporter = class LagReporter {
423
435
  }
424
436
  }, delayMs);
425
437
  }
438
+ #scheduleMissingReportRetry(reportID) {
439
+ clearTimeout(this.#timer);
440
+ this.#timer = setTimeout(async () => {
441
+ this.#timer = void 0;
442
+ const missingReport = this.#expectingLagReport;
443
+ if (missingReport?.id !== reportID) return;
444
+ this.#lagReportRetries.add(1);
445
+ this.#lc.warn?.(`retrying missing lag report`, {
446
+ id: missingReport.id,
447
+ lsn: fromBigInt(missingReport.lsn),
448
+ sendTimeMs: missingReport.sendTimeMs
449
+ });
450
+ try {
451
+ await this.initiateLagReport();
452
+ } catch (e) {
453
+ this.#lc.warn?.(`error retrying lag report`, e);
454
+ this.#scheduleNextReport(this.#lagIntervalMs);
455
+ }
456
+ }, this.#lagIntervalMs);
457
+ }
426
458
  processLagReportMessage(msg) {
427
459
  assert(msg.prefix === this.messagePrefix, `unexpected message prefix: ${msg.prefix}`);
428
460
  const report = parseLogicalMessageContent(this.#lc, msg, lagReportSchema);
@@ -430,9 +462,15 @@ var LagReporter = class LagReporter {
430
462
  }
431
463
  #processLagReport(report, watermark) {
432
464
  const now = Date.now();
433
- const nextSendTimeMs = Math.max(now, report.sendTimeMs + this.#lagIntervalMs);
434
- if (report.id === this.#expectingLagReport?.id) this.#scheduleNextReport(nextSendTimeMs - now);
435
- else this.#lc.debug?.(`received extraneous lag report`, { report });
465
+ const expectedReport = this.#expectingLagReport;
466
+ let nextSendTimeMs;
467
+ if (report.id === expectedReport?.id) {
468
+ nextSendTimeMs = Math.max(now, report.sendTimeMs + this.#lagIntervalMs);
469
+ this.#scheduleNextReport(nextSendTimeMs - now);
470
+ } else {
471
+ this.#lc.debug?.(`received extraneous lag report`, { report });
472
+ nextSendTimeMs = expectedReport?.sendTimeMs ?? Math.max(now, report.sendTimeMs + this.#lagIntervalMs);
473
+ }
436
474
  const { sendTimeMs, commitTimeMs } = report;
437
475
  return [
438
476
  "status",
@@ -581,6 +619,11 @@ var ChangeMaker = class {
581
619
  }
582
620
  const prevEvent = this.#lastReplicationEvent;
583
621
  this.#lastReplicationEvent = event;
622
+ const { schema } = event;
623
+ if (schema === void 0) {
624
+ lc.debug?.(`received context-only ${msg.prefix}/${type} event`, { event: summarizeReplicationEventForLog(event) });
625
+ return [];
626
+ }
584
627
  const prevSchema = event.previousSchema === void 0 ? prevEvent?.schema : event.previousSchema;
585
628
  if (!prevSchema) {
586
629
  lc.info?.(`received ${msg.prefix}/${type} event`, { event: summarizeReplicationEventForLog(event) });
@@ -588,9 +631,9 @@ var ChangeMaker = class {
588
631
  }
589
632
  const effectiveTag = prevEvent?.type === "ddlStart" ? prevEvent.event.tag : event.type === "ddlUpdate" ? event.event.tag : "UNKNOWN";
590
633
  lc.info?.(`processing ${effectiveTag} command from ${msg.prefix}/${type}`, { event: summarizeReplicationEventForLog(event) });
591
- const changes = this.#makeSchemaChanges(lc, prevSchema, event, effectiveTag).map((change) => ["data", change]);
634
+ const changes = this.#makeSchemaChanges(lc, prevSchema, schema, event, effectiveTag).map((change) => ["data", change]);
592
635
  lc.info?.(`${changes.length} schema change(s)`, { changes });
593
- const replicaIdentities = replicaIdentitiesForTablesWithoutPrimaryKeys(event.schema);
636
+ const replicaIdentities = replicaIdentitiesForTablesWithoutPrimaryKeys(schema);
594
637
  if (replicaIdentities) this.#replicaIdentityTimer = setTimeout(async () => {
595
638
  try {
596
639
  await replicaIdentities.apply(lc, this.#db);
@@ -627,10 +670,10 @@ var ChangeMaker = class {
627
670
  * columns. This, for example, would be needed to properly support changing
628
671
  * the type of a column that's indexed.
629
672
  */
630
- #makeSchemaChanges(lc, preSchema, event, tag) {
673
+ #makeSchemaChanges(lc, preSchema, nextSchema, event, tag) {
631
674
  try {
632
675
  const [prevTbl, prevIdx] = specsByID(preSchema);
633
- const [nextTbl, nextIdx] = specsByID(event.schema);
676
+ const [nextTbl, nextIdx] = specsByID(nextSchema);
634
677
  const changes = [];
635
678
  for (const table of nextTbl.values()) validate(lc, table);
636
679
  const [droppedIdx, createdIdx] = symmetricDifferences(prevIdx, nextIdx);
@@ -903,7 +946,7 @@ function summarizeReplicationEventForLog(event) {
903
946
  const { previousSchema, ...eventWithoutSchemas } = rest;
904
947
  return {
905
948
  ...eventWithoutSchemas,
906
- schema: summarizeSchemaForLog(schema),
949
+ ...schema !== void 0 && { schema: summarizeSchemaForLog(schema) },
907
950
  ...previousSchema !== void 0 && { previousSchema: previousSchema === null ? null : summarizeSchemaForLog(previousSchema) }
908
951
  };
909
952
  }