@rocicorp/zero 1.8.0-canary.5 → 1.8.0-canary.7

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 (86) hide show
  1. package/README.md +6 -23
  2. package/out/analyze-query/src/bin-analyze.js +1 -1
  3. package/out/zero/package.js +1 -1
  4. package/out/zero/package.js.map +1 -1
  5. package/out/zero/src/zero.js +1 -1
  6. package/out/zero-cache/src/custom/fetch.js +1 -1
  7. package/out/zero-cache/src/custom-queries/transform-query.js +1 -1
  8. package/out/zero-cache/src/db/migration-lite.d.ts +0 -6
  9. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  10. package/out/zero-cache/src/db/migration-lite.js +2 -22
  11. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  12. package/out/zero-cache/src/observability/metrics.d.ts +3 -0
  13. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  14. package/out/zero-cache/src/observability/metrics.js +21 -1
  15. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  16. package/out/zero-cache/src/server/anonymous-otel-start.js +1 -1
  17. package/out/zero-cache/src/server/inspector-delegate.js +1 -1
  18. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  19. package/out/zero-cache/src/server/main.js +4 -2
  20. package/out/zero-cache/src/server/main.js.map +1 -1
  21. package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
  22. package/out/zero-cache/src/server/otel-start.js +7 -0
  23. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  24. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  25. package/out/zero-cache/src/services/change-source/common/replica-schema.js +2 -2
  26. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  27. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  28. package/out/zero-cache/src/services/change-source/pg/change-source.js +4 -0
  29. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  30. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.d.ts +15 -0
  31. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.d.ts.map +1 -0
  32. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.js +72 -0
  33. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.js.map +1 -0
  34. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +2 -0
  35. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  36. package/out/zero-cache/src/services/change-streamer/broadcast.js +11 -4
  37. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  38. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  39. package/out/zero-cache/src/services/change-streamer/forwarder.js +43 -2
  40. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  41. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  42. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  43. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +8 -2
  44. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  45. package/out/zero-cache/src/services/change-streamer/subscriber.js +112 -12
  46. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  47. package/out/zero-cache/src/services/life-cycle.d.ts +1 -0
  48. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  49. package/out/zero-cache/src/services/life-cycle.js +41 -1
  50. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  51. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  52. package/out/zero-cache/src/services/litestream/commands.js +0 -2
  53. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  54. package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
  55. package/out/zero-cache/src/services/litestream/metrics.js +14 -29
  56. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  57. package/out/zero-cache/src/services/mutagen/pusher.js +1 -1
  58. package/out/zero-cache/src/services/shadow-sync/shadow-sync-service.js +10 -6
  59. package/out/zero-cache/src/services/shadow-sync/shadow-sync-service.js.map +1 -1
  60. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  61. package/out/zero-cache/src/services/view-syncer/cvr-store.js +48 -11
  62. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  63. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  64. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +12 -0
  65. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  66. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  67. package/out/zero-cache/src/services/view-syncer/view-syncer.js +10 -3
  68. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  69. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  70. package/out/zero-cache/src/workers/connection.js +12 -0
  71. package/out/zero-cache/src/workers/connection.js.map +1 -1
  72. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  73. package/out/zero-cache/src/workers/syncer.js +72 -22
  74. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  75. package/out/zero-client/src/client/mutation-tracker.js +1 -1
  76. package/out/zero-client/src/client/query-manager.js +2 -2
  77. package/out/zero-client/src/client/version.js +1 -1
  78. package/out/zero-client/src/client/zero.js +3 -3
  79. package/out/zero-client/src/mod.d.ts +4 -4
  80. package/out/zero-client/src/mod.d.ts.map +1 -1
  81. package/out/zero-client/src/mod.js +1 -1
  82. package/out/zero-react/src/zero.js +1 -1
  83. package/out/zero-server/src/custom.js +1 -1
  84. package/out/zero-server/src/queries/process-queries.js +3 -3
  85. package/out/zero-solid/src/zero.js +1 -1
  86. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/litestream/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,6BAA6B,CAAC;AAM5D,MAAM,MAAM,cAAc,GAAG,qBAAqB,GAAG,aAAa,CAAC;AACnE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CAAC;AAEhD,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AAEF,KAAK,8BAA8B,GAAG;IACpC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAMF,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,cAAc,EACpB,SAAS,qBAA8B,GACtC,qBAAqB,GAAG,8BAA8B,CAaxD;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,UAAU,GACjB,qBAAqB,CAUvB;AAED,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,UAAU,GACjB,qBAAqB,GAAG,8BAA8B,CAKxD;AAED,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,iBAAiB,EAC7B,IAAI,EAAE,cAAc,GACnB,qBAAqB,CAMvB;AAyBD,wBAAgB,qBAAqB,kFAMpC;AAED,wBAAgB,yBAAyB,kFAMxC;AAED,wBAAgB,yBAAyB,kFAMxC;AAED,wBAAgB,2BAA2B,kFAM1C;AAED,wBAAgB,yBAAyB,8DAKxC;AAED,wBAAgB,6BAA6B,8DAK5C;AAED,wBAAgB,gCAAgC,8DAK/C;AAED,wBAAgB,mCAAmC,8DAKlD;AAED,wBAAgB,+BAA+B,8DAK9C;AAED,wBAAgB,4BAA4B,8DAK3C;AAED,wBAAgB,oCAAoC,8DAKnD;AAED,wBAAgB,qCAAqC,8DAKpD"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/litestream/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,6BAA6B,CAAC;AAO5D,MAAM,MAAM,cAAc,GAAG,qBAAqB,GAAG,aAAa,CAAC;AACnE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,IAAI,CAAC;AAEhD,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AAEF,KAAK,8BAA8B,GAAG;IACpC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,cAAc,EACpB,SAAS,qBAA8B,GACtC,qBAAqB,GAAG,8BAA8B,CAaxD;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,UAAU,GACjB,qBAAqB,CAUvB;AAED,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,UAAU,GACjB,qBAAqB,GAAG,8BAA8B,CAKxD;AAED,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,iBAAiB,EAC7B,IAAI,EAAE,cAAc,GACnB,qBAAqB,CAMvB;AAyBD,wBAAgB,qBAAqB,kFAMpC;AAED,wBAAgB,yBAAyB,kFAMxC;AAED,wBAAgB,yBAAyB,kFAMxC;AAED,wBAAgB,2BAA2B,kFAM1C;AAED,wBAAgB,yBAAyB,8DAKxC;AAED,wBAAgB,6BAA6B,8DAK5C;AAED,wBAAgB,gCAAgC,8DAK/C;AAED,wBAAgB,mCAAmC,8DAKlD;AAED,wBAAgB,+BAA+B,8DAK9C;AAED,wBAAgB,4BAA4B,8DAK3C;AAED,wBAAgB,oCAAoC,8DAKnD;AAED,wBAAgB,qCAAqC,8DAKpD"}
@@ -1,20 +1,5 @@
1
- import { getOrCreateCounter, getOrCreateHistogram } from "../../observability/metrics.js";
1
+ import { LONG_DURATION_HISTOGRAM_BOUNDARIES_S, getOrCreateCounter, getOrCreateHistogram } from "../../observability/metrics.js";
2
2
  //#region ../zero-cache/src/services/litestream/metrics.ts
3
- var LITESTREAM_DURATION_HISTOGRAM_BOUNDARIES_S = [
4
- 1,
5
- 2,
6
- 5,
7
- 10,
8
- 30,
9
- 60,
10
- 120,
11
- 300,
12
- 600,
13
- 1200,
14
- 2400,
15
- 3600,
16
- 7200
17
- ];
18
3
  function litestreamRestoreMetricAttrs(config, role, backupURL = config.litestream.backupURL) {
19
4
  const { executable, executableV5, restoreUsingV5 } = config.litestream;
20
5
  const selectedExecutable = (restoreUsingV5 ? executableV5 : executable) ?? executable;
@@ -61,49 +46,49 @@ function litestreamMultipartMetricAttrs(config) {
61
46
  };
62
47
  }
63
48
  function litestreamRestoreRuns() {
64
- return getOrCreateCounter("replica", "litestream_restore_runs", "Litestream restore runs, labeled by result.");
49
+ return getOrCreateCounter("replica", "litestream.restore.runs", "Litestream restore runs, labeled by result.");
65
50
  }
66
51
  function litestreamRestoreAttempts() {
67
- return getOrCreateCounter("replica", "litestream_restore_attempts", "Litestream restore subprocess attempts, labeled by result.");
52
+ return getOrCreateCounter("replica", "litestream.restore.attempts", "Litestream restore subprocess attempts, labeled by result.");
68
53
  }
69
54
  function litestreamRestoredDbBytes() {
70
- return getOrCreateCounter("replica", "litestream_restored_db", {
55
+ return getOrCreateCounter("replica", "litestream.restore.db_bytes", {
71
56
  description: "SQLite database bytes restored by successful litestream restores.",
72
57
  unit: "bytes"
73
58
  });
74
59
  }
75
60
  function litestreamBackupProcessRuns() {
76
- return getOrCreateCounter("replica", "litestream_backup_process_runs", "Litestream backup process exits, labeled by result.");
61
+ return getOrCreateCounter("replica", "litestream.backup.process_runs", "Litestream backup process exits, labeled by result.");
77
62
  }
78
63
  function litestreamRestoreDuration() {
79
- return litestreamDurationHistogram("litestream_restore_duration", "Wall-clock duration of a litestream restore run, labeled by result.");
64
+ return litestreamDurationHistogram("litestream.restore.duration", "Wall-clock duration of a litestream restore run, labeled by result.");
80
65
  }
81
66
  function litestreamRestoreWaitDuration() {
82
- return litestreamDurationHistogram("litestream_restore_wait_duration", "Time spent waiting for the replication-manager snapshot status before restoring.");
67
+ return litestreamDurationHistogram("litestream.restore.wait_duration", "Time spent waiting for the replication-manager snapshot status before restoring.");
83
68
  }
84
69
  function litestreamRestoreProcessDuration() {
85
- return litestreamDurationHistogram("litestream_restore_process_duration", "Wall-clock duration of the litestream restore subprocess.");
70
+ return litestreamDurationHistogram("litestream.restore.process_duration", "Wall-clock duration of the litestream restore subprocess.");
86
71
  }
87
72
  function litestreamRestoreValidationDuration() {
88
- return litestreamDurationHistogram("litestream_restore_validation_duration", "Time spent validating a restored replica database.");
73
+ return litestreamDurationHistogram("litestream.restore.validation_duration", "Time spent validating a restored replica database.");
89
74
  }
90
75
  function litestreamBackupProcessDuration() {
91
- return litestreamDurationHistogram("litestream_backup_process_duration", "Runtime duration of the litestream backup subprocess before it exits.");
76
+ return litestreamDurationHistogram("litestream.backup.process_duration", "Runtime duration of the litestream backup subprocess before it exits.");
92
77
  }
93
78
  function litestreamBackupListDuration() {
94
- return litestreamDurationHistogram("litestream_backup_list_duration", "Duration of litestream backup destination listing commands.");
79
+ return litestreamDurationHistogram("litestream.backup.list_duration", "Duration of litestream backup destination listing commands.");
95
80
  }
96
81
  function litestreamBackupVerificationDuration() {
97
- return litestreamDurationHistogram("litestream_backup_verification_duration", "Duration of verifying the actual backup state in the backup destination.");
82
+ return litestreamDurationHistogram("litestream.backup.verification_duration", "Duration of verifying the actual backup state in the backup destination.");
98
83
  }
99
84
  function litestreamSnapshotReservationDuration() {
100
- return litestreamDurationHistogram("litestream_snapshot_reservation_duration", "Duration of a snapshot reservation while a view-syncer restores and subscribes.");
85
+ return litestreamDurationHistogram("litestream.snapshot.reservation_duration", "Duration of a snapshot reservation while a view-syncer restores and subscribes.");
101
86
  }
102
87
  function litestreamDurationHistogram(name, description) {
103
88
  return getOrCreateHistogram("replica", name, {
104
89
  description,
105
90
  unit: "s",
106
- bucketBoundaries: LITESTREAM_DURATION_HISTOGRAM_BOUNDARIES_S
91
+ bucketBoundaries: LONG_DURATION_HISTOGRAM_BOUNDARIES_S
107
92
  });
108
93
  }
109
94
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","names":[],"sources":["../../../../../../zero-cache/src/services/litestream/metrics.ts"],"sourcesContent":["import type {ZeroConfig} from '../../config/zero-config.ts';\nimport {\n getOrCreateCounter,\n getOrCreateHistogram,\n} from '../../observability/metrics.ts';\n\nexport type LitestreamRole = 'replication_manager' | 'view_syncer';\nexport type LitestreamVersion = 'legacy' | 'v5';\n\nexport type LitestreamMetricAttrs = {\n role: LitestreamRole;\n backup_scheme: string;\n litestream: LitestreamVersion;\n};\n\ntype LitestreamMultipartMetricAttrs = {\n multipart_concurrency: number;\n multipart_size_mib: number;\n};\n\nconst LITESTREAM_DURATION_HISTOGRAM_BOUNDARIES_S = [\n 1, 2, 5, 10, 30, 60, 120, 300, 600, 1200, 2400, 3600, 7200,\n];\n\nexport function litestreamRestoreMetricAttrs(\n config: ZeroConfig,\n role: LitestreamRole,\n backupURL = config.litestream.backupURL,\n): LitestreamMetricAttrs & LitestreamMultipartMetricAttrs {\n const {executable, executableV5, restoreUsingV5} = config.litestream;\n const selectedExecutable =\n (restoreUsingV5 ? executableV5 : executable) ?? executable;\n return {\n role,\n backup_scheme: litestreamBackupScheme(backupURL),\n litestream:\n executableV5 !== undefined && selectedExecutable === executableV5\n ? 'v5'\n : 'legacy',\n ...litestreamMultipartMetricAttrs(config),\n };\n}\n\nexport function litestreamBackupMetricAttrs(\n config: ZeroConfig,\n): LitestreamMetricAttrs {\n return {\n role: 'replication_manager',\n backup_scheme: litestreamBackupScheme(config.litestream.backupURL),\n litestream:\n config.litestream.executableV5 !== undefined &&\n config.litestream.executable === config.litestream.executableV5\n ? 'v5'\n : 'legacy',\n };\n}\n\nexport function litestreamBackupProcessMetricAttrs(\n config: ZeroConfig,\n): LitestreamMetricAttrs & LitestreamMultipartMetricAttrs {\n return {\n ...litestreamBackupMetricAttrs(config),\n ...litestreamMultipartMetricAttrs(config),\n };\n}\n\nexport function litestreamMonitorMetricAttrs(\n backupURL: string,\n litestream: LitestreamVersion,\n role: LitestreamRole,\n): LitestreamMetricAttrs {\n return {\n role,\n backup_scheme: litestreamBackupScheme(backupURL),\n litestream,\n };\n}\n\nfunction litestreamBackupScheme(backupURL: string | undefined): string {\n if (!backupURL) {\n return 'unknown';\n }\n try {\n const protocol = new URL(backupURL).protocol;\n return protocol.endsWith(':') ? protocol.slice(0, -1) : protocol;\n } catch {\n return 'unknown';\n }\n}\n\nfunction litestreamMultipartMetricAttrs(\n config: ZeroConfig,\n): LitestreamMultipartMetricAttrs {\n return {\n multipart_concurrency: config.litestream.multipartConcurrency,\n multipart_size_mib: Math.round(\n config.litestream.multipartSize / 1024 / 1024,\n ),\n };\n}\n\nexport function litestreamRestoreRuns() {\n return getOrCreateCounter(\n 'replica',\n 'litestream_restore_runs',\n 'Litestream restore runs, labeled by result.',\n );\n}\n\nexport function litestreamRestoreAttempts() {\n return getOrCreateCounter(\n 'replica',\n 'litestream_restore_attempts',\n 'Litestream restore subprocess attempts, labeled by result.',\n );\n}\n\nexport function litestreamRestoredDbBytes() {\n return getOrCreateCounter('replica', 'litestream_restored_db', {\n description:\n 'SQLite database bytes restored by successful litestream restores.',\n unit: 'bytes',\n });\n}\n\nexport function litestreamBackupProcessRuns() {\n return getOrCreateCounter(\n 'replica',\n 'litestream_backup_process_runs',\n 'Litestream backup process exits, labeled by result.',\n );\n}\n\nexport function litestreamRestoreDuration() {\n return litestreamDurationHistogram(\n 'litestream_restore_duration',\n 'Wall-clock duration of a litestream restore run, labeled by result.',\n );\n}\n\nexport function litestreamRestoreWaitDuration() {\n return litestreamDurationHistogram(\n 'litestream_restore_wait_duration',\n 'Time spent waiting for the replication-manager snapshot status before restoring.',\n );\n}\n\nexport function litestreamRestoreProcessDuration() {\n return litestreamDurationHistogram(\n 'litestream_restore_process_duration',\n 'Wall-clock duration of the litestream restore subprocess.',\n );\n}\n\nexport function litestreamRestoreValidationDuration() {\n return litestreamDurationHistogram(\n 'litestream_restore_validation_duration',\n 'Time spent validating a restored replica database.',\n );\n}\n\nexport function litestreamBackupProcessDuration() {\n return litestreamDurationHistogram(\n 'litestream_backup_process_duration',\n 'Runtime duration of the litestream backup subprocess before it exits.',\n );\n}\n\nexport function litestreamBackupListDuration() {\n return litestreamDurationHistogram(\n 'litestream_backup_list_duration',\n 'Duration of litestream backup destination listing commands.',\n );\n}\n\nexport function litestreamBackupVerificationDuration() {\n return litestreamDurationHistogram(\n 'litestream_backup_verification_duration',\n 'Duration of verifying the actual backup state in the backup destination.',\n );\n}\n\nexport function litestreamSnapshotReservationDuration() {\n return litestreamDurationHistogram(\n 'litestream_snapshot_reservation_duration',\n 'Duration of a snapshot reservation while a view-syncer restores and subscribes.',\n );\n}\n\nfunction litestreamDurationHistogram(name: string, description: string) {\n return getOrCreateHistogram('replica', name, {\n description,\n unit: 's',\n bucketBoundaries: LITESTREAM_DURATION_HISTOGRAM_BOUNDARIES_S,\n });\n}\n"],"mappings":";;AAoBA,IAAM,6CAA6C;CACjD;CAAG;CAAG;CAAG;CAAI;CAAI;CAAI;CAAK;CAAK;CAAK;CAAM;CAAM;CAAM;AACxD;AAEA,SAAgB,6BACd,QACA,MACA,YAAY,OAAO,WAAW,WAC0B;CACxD,MAAM,EAAC,YAAY,cAAc,mBAAkB,OAAO;CAC1D,MAAM,sBACH,iBAAiB,eAAe,eAAe;CAClD,OAAO;EACL;EACA,eAAe,uBAAuB,SAAS;EAC/C,YACE,iBAAiB,KAAA,KAAa,uBAAuB,eACjD,OACA;EACN,GAAG,+BAA+B,MAAM;CAC1C;AACF;AAEA,SAAgB,4BACd,QACuB;CACvB,OAAO;EACL,MAAM;EACN,eAAe,uBAAuB,OAAO,WAAW,SAAS;EACjE,YACE,OAAO,WAAW,iBAAiB,KAAA,KACnC,OAAO,WAAW,eAAe,OAAO,WAAW,eAC/C,OACA;CACR;AACF;AAEA,SAAgB,mCACd,QACwD;CACxD,OAAO;EACL,GAAG,4BAA4B,MAAM;EACrC,GAAG,+BAA+B,MAAM;CAC1C;AACF;AAEA,SAAgB,6BACd,WACA,YACA,MACuB;CACvB,OAAO;EACL;EACA,eAAe,uBAAuB,SAAS;EAC/C;CACF;AACF;AAEA,SAAS,uBAAuB,WAAuC;CACrE,IAAI,CAAC,WACH,OAAO;CAET,IAAI;EACF,MAAM,WAAW,IAAI,IAAI,SAAS,EAAE;EACpC,OAAO,SAAS,SAAS,GAAG,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI;CAC1D,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,+BACP,QACgC;CAChC,OAAO;EACL,uBAAuB,OAAO,WAAW;EACzC,oBAAoB,KAAK,MACvB,OAAO,WAAW,gBAAgB,OAAO,IAC3C;CACF;AACF;AAEA,SAAgB,wBAAwB;CACtC,OAAO,mBACL,WACA,2BACA,6CACF;AACF;AAEA,SAAgB,4BAA4B;CAC1C,OAAO,mBACL,WACA,+BACA,4DACF;AACF;AAEA,SAAgB,4BAA4B;CAC1C,OAAO,mBAAmB,WAAW,0BAA0B;EAC7D,aACE;EACF,MAAM;CACR,CAAC;AACH;AAEA,SAAgB,8BAA8B;CAC5C,OAAO,mBACL,WACA,kCACA,qDACF;AACF;AAEA,SAAgB,4BAA4B;CAC1C,OAAO,4BACL,+BACA,qEACF;AACF;AAEA,SAAgB,gCAAgC;CAC9C,OAAO,4BACL,oCACA,kFACF;AACF;AAEA,SAAgB,mCAAmC;CACjD,OAAO,4BACL,uCACA,2DACF;AACF;AAEA,SAAgB,sCAAsC;CACpD,OAAO,4BACL,0CACA,oDACF;AACF;AAEA,SAAgB,kCAAkC;CAChD,OAAO,4BACL,sCACA,uEACF;AACF;AAEA,SAAgB,+BAA+B;CAC7C,OAAO,4BACL,mCACA,6DACF;AACF;AAEA,SAAgB,uCAAuC;CACrD,OAAO,4BACL,2CACA,0EACF;AACF;AAEA,SAAgB,wCAAwC;CACtD,OAAO,4BACL,4CACA,iFACF;AACF;AAEA,SAAS,4BAA4B,MAAc,aAAqB;CACtE,OAAO,qBAAqB,WAAW,MAAM;EAC3C;EACA,MAAM;EACN,kBAAkB;CACpB,CAAC;AACH"}
1
+ {"version":3,"file":"metrics.js","names":[],"sources":["../../../../../../zero-cache/src/services/litestream/metrics.ts"],"sourcesContent":["import type {ZeroConfig} from '../../config/zero-config.ts';\nimport {\n getOrCreateCounter,\n getOrCreateHistogram,\n LONG_DURATION_HISTOGRAM_BOUNDARIES_S,\n} from '../../observability/metrics.ts';\n\nexport type LitestreamRole = 'replication_manager' | 'view_syncer';\nexport type LitestreamVersion = 'legacy' | 'v5';\n\nexport type LitestreamMetricAttrs = {\n role: LitestreamRole;\n backup_scheme: string;\n litestream: LitestreamVersion;\n};\n\ntype LitestreamMultipartMetricAttrs = {\n multipart_concurrency: number;\n multipart_size_mib: number;\n};\n\nexport function litestreamRestoreMetricAttrs(\n config: ZeroConfig,\n role: LitestreamRole,\n backupURL = config.litestream.backupURL,\n): LitestreamMetricAttrs & LitestreamMultipartMetricAttrs {\n const {executable, executableV5, restoreUsingV5} = config.litestream;\n const selectedExecutable =\n (restoreUsingV5 ? executableV5 : executable) ?? executable;\n return {\n role,\n backup_scheme: litestreamBackupScheme(backupURL),\n litestream:\n executableV5 !== undefined && selectedExecutable === executableV5\n ? 'v5'\n : 'legacy',\n ...litestreamMultipartMetricAttrs(config),\n };\n}\n\nexport function litestreamBackupMetricAttrs(\n config: ZeroConfig,\n): LitestreamMetricAttrs {\n return {\n role: 'replication_manager',\n backup_scheme: litestreamBackupScheme(config.litestream.backupURL),\n litestream:\n config.litestream.executableV5 !== undefined &&\n config.litestream.executable === config.litestream.executableV5\n ? 'v5'\n : 'legacy',\n };\n}\n\nexport function litestreamBackupProcessMetricAttrs(\n config: ZeroConfig,\n): LitestreamMetricAttrs & LitestreamMultipartMetricAttrs {\n return {\n ...litestreamBackupMetricAttrs(config),\n ...litestreamMultipartMetricAttrs(config),\n };\n}\n\nexport function litestreamMonitorMetricAttrs(\n backupURL: string,\n litestream: LitestreamVersion,\n role: LitestreamRole,\n): LitestreamMetricAttrs {\n return {\n role,\n backup_scheme: litestreamBackupScheme(backupURL),\n litestream,\n };\n}\n\nfunction litestreamBackupScheme(backupURL: string | undefined): string {\n if (!backupURL) {\n return 'unknown';\n }\n try {\n const protocol = new URL(backupURL).protocol;\n return protocol.endsWith(':') ? protocol.slice(0, -1) : protocol;\n } catch {\n return 'unknown';\n }\n}\n\nfunction litestreamMultipartMetricAttrs(\n config: ZeroConfig,\n): LitestreamMultipartMetricAttrs {\n return {\n multipart_concurrency: config.litestream.multipartConcurrency,\n multipart_size_mib: Math.round(\n config.litestream.multipartSize / 1024 / 1024,\n ),\n };\n}\n\nexport function litestreamRestoreRuns() {\n return getOrCreateCounter(\n 'replica',\n 'litestream.restore.runs',\n 'Litestream restore runs, labeled by result.',\n );\n}\n\nexport function litestreamRestoreAttempts() {\n return getOrCreateCounter(\n 'replica',\n 'litestream.restore.attempts',\n 'Litestream restore subprocess attempts, labeled by result.',\n );\n}\n\nexport function litestreamRestoredDbBytes() {\n return getOrCreateCounter('replica', 'litestream.restore.db_bytes', {\n description:\n 'SQLite database bytes restored by successful litestream restores.',\n unit: 'bytes',\n });\n}\n\nexport function litestreamBackupProcessRuns() {\n return getOrCreateCounter(\n 'replica',\n 'litestream.backup.process_runs',\n 'Litestream backup process exits, labeled by result.',\n );\n}\n\nexport function litestreamRestoreDuration() {\n return litestreamDurationHistogram(\n 'litestream.restore.duration',\n 'Wall-clock duration of a litestream restore run, labeled by result.',\n );\n}\n\nexport function litestreamRestoreWaitDuration() {\n return litestreamDurationHistogram(\n 'litestream.restore.wait_duration',\n 'Time spent waiting for the replication-manager snapshot status before restoring.',\n );\n}\n\nexport function litestreamRestoreProcessDuration() {\n return litestreamDurationHistogram(\n 'litestream.restore.process_duration',\n 'Wall-clock duration of the litestream restore subprocess.',\n );\n}\n\nexport function litestreamRestoreValidationDuration() {\n return litestreamDurationHistogram(\n 'litestream.restore.validation_duration',\n 'Time spent validating a restored replica database.',\n );\n}\n\nexport function litestreamBackupProcessDuration() {\n return litestreamDurationHistogram(\n 'litestream.backup.process_duration',\n 'Runtime duration of the litestream backup subprocess before it exits.',\n );\n}\n\nexport function litestreamBackupListDuration() {\n return litestreamDurationHistogram(\n 'litestream.backup.list_duration',\n 'Duration of litestream backup destination listing commands.',\n );\n}\n\nexport function litestreamBackupVerificationDuration() {\n return litestreamDurationHistogram(\n 'litestream.backup.verification_duration',\n 'Duration of verifying the actual backup state in the backup destination.',\n );\n}\n\nexport function litestreamSnapshotReservationDuration() {\n return litestreamDurationHistogram(\n 'litestream.snapshot.reservation_duration',\n 'Duration of a snapshot reservation while a view-syncer restores and subscribes.',\n );\n}\n\nfunction litestreamDurationHistogram(name: string, description: string) {\n return getOrCreateHistogram('replica', name, {\n description,\n unit: 's',\n bucketBoundaries: LONG_DURATION_HISTOGRAM_BOUNDARIES_S,\n });\n}\n"],"mappings":";;AAqBA,SAAgB,6BACd,QACA,MACA,YAAY,OAAO,WAAW,WAC0B;CACxD,MAAM,EAAC,YAAY,cAAc,mBAAkB,OAAO;CAC1D,MAAM,sBACH,iBAAiB,eAAe,eAAe;CAClD,OAAO;EACL;EACA,eAAe,uBAAuB,SAAS;EAC/C,YACE,iBAAiB,KAAA,KAAa,uBAAuB,eACjD,OACA;EACN,GAAG,+BAA+B,MAAM;CAC1C;AACF;AAEA,SAAgB,4BACd,QACuB;CACvB,OAAO;EACL,MAAM;EACN,eAAe,uBAAuB,OAAO,WAAW,SAAS;EACjE,YACE,OAAO,WAAW,iBAAiB,KAAA,KACnC,OAAO,WAAW,eAAe,OAAO,WAAW,eAC/C,OACA;CACR;AACF;AAEA,SAAgB,mCACd,QACwD;CACxD,OAAO;EACL,GAAG,4BAA4B,MAAM;EACrC,GAAG,+BAA+B,MAAM;CAC1C;AACF;AAEA,SAAgB,6BACd,WACA,YACA,MACuB;CACvB,OAAO;EACL;EACA,eAAe,uBAAuB,SAAS;EAC/C;CACF;AACF;AAEA,SAAS,uBAAuB,WAAuC;CACrE,IAAI,CAAC,WACH,OAAO;CAET,IAAI;EACF,MAAM,WAAW,IAAI,IAAI,SAAS,EAAE;EACpC,OAAO,SAAS,SAAS,GAAG,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI;CAC1D,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,+BACP,QACgC;CAChC,OAAO;EACL,uBAAuB,OAAO,WAAW;EACzC,oBAAoB,KAAK,MACvB,OAAO,WAAW,gBAAgB,OAAO,IAC3C;CACF;AACF;AAEA,SAAgB,wBAAwB;CACtC,OAAO,mBACL,WACA,2BACA,6CACF;AACF;AAEA,SAAgB,4BAA4B;CAC1C,OAAO,mBACL,WACA,+BACA,4DACF;AACF;AAEA,SAAgB,4BAA4B;CAC1C,OAAO,mBAAmB,WAAW,+BAA+B;EAClE,aACE;EACF,MAAM;CACR,CAAC;AACH;AAEA,SAAgB,8BAA8B;CAC5C,OAAO,mBACL,WACA,kCACA,qDACF;AACF;AAEA,SAAgB,4BAA4B;CAC1C,OAAO,4BACL,+BACA,qEACF;AACF;AAEA,SAAgB,gCAAgC;CAC9C,OAAO,4BACL,oCACA,kFACF;AACF;AAEA,SAAgB,mCAAmC;CACjD,OAAO,4BACL,uCACA,2DACF;AACF;AAEA,SAAgB,sCAAsC;CACpD,OAAO,4BACL,0CACA,oDACF;AACF;AAEA,SAAgB,kCAAkC;CAChD,OAAO,4BACL,sCACA,uEACF;AACF;AAEA,SAAgB,+BAA+B;CAC7C,OAAO,4BACL,mCACA,6DACF;AACF;AAEA,SAAgB,uCAAuC;CACrD,OAAO,4BACL,2CACA,0EACF;AACF;AAEA,SAAgB,wCAAwC;CACtD,OAAO,4BACL,4CACA,iFACF;AACF;AAEA,SAAS,4BAA4B,MAAc,aAAqB;CACtE,OAAO,qBAAqB,WAAW,MAAM;EAC3C;EACA,MAAM;EACN,kBAAkB;CACpB,CAAC;AACH"}
@@ -1,7 +1,7 @@
1
1
  import { assert } from "../../../../shared/src/asserts.js";
2
- import { getErrorMessage } from "../../../../shared/src/error.js";
3
2
  import { groupBy } from "../../../../shared/src/arrays.js";
4
3
  import { must } from "../../../../shared/src/must.js";
4
+ import { getErrorMessage } from "../../../../shared/src/error.js";
5
5
  import { PushFailed } from "../../../../zero-protocol/src/error-kind-enum.js";
6
6
  import { Server, ZeroCache } from "../../../../zero-protocol/src/error-origin-enum.js";
7
7
  import { HTTP, Internal, OutOfOrderMutation, UnsupportedPushVersion } from "../../../../zero-protocol/src/error-reason-enum.js";
@@ -3,8 +3,12 @@ import { getOrCreateCounter, getOrCreateLatencyHistogram } from "../../observabi
3
3
  import { RunningState } from "../running-state.js";
4
4
  import { shadowInitialSync } from "../change-source/pg/initial-sync.js";
5
5
  //#region ../zero-cache/src/services/shadow-sync/shadow-sync-service.ts
6
- var shadowSyncRuns = getOrCreateCounter("replication", "shadow-sync-runs", "Number of shadow initial-sync runs, labeled by result.");
7
- var shadowSyncDuration = getOrCreateLatencyHistogram("replication", "shadow-sync-duration", "Wall-clock duration of a shadow initial-sync run, labeled by result.");
6
+ function shadowSyncRuns() {
7
+ return getOrCreateCounter("replication", "shadow-sync-runs", "Number of shadow initial-sync runs, labeled by result.");
8
+ }
9
+ function shadowSyncDuration() {
10
+ return getOrCreateLatencyHistogram("replication", "shadow-sync-duration", "Wall-clock duration of a shadow initial-sync run, labeled by result.");
11
+ }
8
12
  var ShadowSyncService = class {
9
13
  id = "shadow-syncer";
10
14
  #lc;
@@ -34,13 +38,13 @@ var ShadowSyncService = class {
34
38
  maxRowsPerTable
35
39
  }, this.#context, textCopy !== void 0 ? { textCopy } : void 0);
36
40
  const elapsed = performance.now() - start;
37
- shadowSyncRuns.add(1, { result: "success" });
38
- shadowSyncDuration.recordMs(elapsed, { result: "success" });
41
+ shadowSyncRuns().add(1, { result: "success" });
42
+ shadowSyncDuration().recordMs(elapsed, { result: "success" });
39
43
  this.#lc.info?.(`shadow initial-sync completed (${elapsed.toFixed(0)} ms)`);
40
44
  } catch (e) {
41
45
  const elapsed = performance.now() - start;
42
- shadowSyncRuns.add(1, { result: "error" });
43
- shadowSyncDuration.recordMs(elapsed, { result: "error" });
46
+ shadowSyncRuns().add(1, { result: "error" });
47
+ shadowSyncDuration().recordMs(elapsed, { result: "error" });
44
48
  this.#lc.error?.(`shadow initial-sync failed after ${elapsed.toFixed(0)} ms`, e);
45
49
  }
46
50
  await this.#state.sleep(intervalMs);
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-sync-service.js","names":["#lc","#shard","#upstreamURI","#context","#options","#state"],"sources":["../../../../../../zero-cache/src/services/shadow-sync/shadow-sync-service.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {promiseVoid} from '../../../../shared/src/resolved-promises.ts';\nimport {\n getOrCreateCounter,\n getOrCreateLatencyHistogram,\n} from '../../observability/metrics.ts';\nimport type {ShardConfig} from '../../types/shards.ts';\nimport type {ServerContext} from '../change-source/pg/initial-sync.ts';\nimport {shadowInitialSync} from '../change-source/pg/initial-sync.ts';\nimport {RunningState} from '../running-state.ts';\nimport type {Service} from '../service.ts';\n\nconst shadowSyncRuns = getOrCreateCounter(\n 'replication',\n 'shadow-sync-runs',\n 'Number of shadow initial-sync runs, labeled by result.',\n);\n\nconst shadowSyncDuration = getOrCreateLatencyHistogram(\n 'replication',\n 'shadow-sync-duration',\n 'Wall-clock duration of a shadow initial-sync run, labeled by result.',\n);\n\nexport type ShadowSyncOptions = {\n intervalMs: number;\n sampleRate: number;\n maxRowsPerTable: number;\n textCopy?: boolean | undefined;\n};\n\nexport class ShadowSyncService implements Service {\n readonly id = 'shadow-syncer';\n\n readonly #lc: LogContext;\n readonly #shard: ShardConfig;\n readonly #upstreamURI: string;\n readonly #context: ServerContext;\n readonly #options: ShadowSyncOptions;\n readonly #state = new RunningState('shadow-syncer');\n\n constructor(\n lc: LogContext,\n shard: ShardConfig,\n upstreamURI: string,\n context: ServerContext,\n options: ShadowSyncOptions,\n ) {\n this.#lc = lc;\n this.#shard = shard;\n this.#upstreamURI = upstreamURI;\n this.#context = context;\n this.#options = options;\n }\n\n async run() {\n const {intervalMs, sampleRate, maxRowsPerTable, textCopy} = this.#options;\n\n // Why: first run fires in [intervalMs * 2/3, intervalMs) — late enough\n // that shadow sync never fires immediately on task startup, but always\n // before one full interval elapses so the canary completes at least once\n // per task lifetime (the replication manager is restarted every ~24h).\n // The last third is randomized so a fleet-wide restart does not cause\n // every task to canary simultaneously.\n const minFirstRunDelay = Math.floor((intervalMs * 2) / 3);\n const firstRunDelay =\n minFirstRunDelay +\n Math.floor(Math.random() * (intervalMs - minFirstRunDelay));\n this.#lc.info?.(\n `shadow-syncer started; first run in ${firstRunDelay} ms, then every ${intervalMs} ms`,\n );\n await this.#state.sleep(firstRunDelay);\n\n while (this.#state.shouldRun()) {\n const start = performance.now();\n try {\n await shadowInitialSync(\n this.#lc,\n this.#shard,\n this.#upstreamURI,\n {sampleRate, maxRowsPerTable},\n this.#context,\n textCopy !== undefined ? {textCopy} : undefined,\n );\n const elapsed = performance.now() - start;\n shadowSyncRuns.add(1, {result: 'success'});\n shadowSyncDuration.recordMs(elapsed, {result: 'success'});\n this.#lc.info?.(\n `shadow initial-sync completed (${elapsed.toFixed(0)} ms)`,\n );\n } catch (e) {\n const elapsed = performance.now() - start;\n shadowSyncRuns.add(1, {result: 'error'});\n shadowSyncDuration.recordMs(elapsed, {result: 'error'});\n this.#lc.error?.(\n `shadow initial-sync failed after ${elapsed.toFixed(0)} ms`,\n e,\n );\n }\n await this.#state.sleep(intervalMs);\n }\n }\n\n stop(): Promise<void> {\n this.#state.stop(this.#lc);\n return promiseVoid;\n }\n}\n"],"mappings":";;;;;AAYA,IAAM,iBAAiB,mBACrB,eACA,oBACA,wDACF;AAEA,IAAM,qBAAqB,4BACzB,eACA,wBACA,sEACF;AASA,IAAa,oBAAb,MAAkD;CAChD,KAAc;CAEd;CACA;CACA;CACA;CACA;CACA,SAAkB,IAAI,aAAa,eAAe;CAElD,YACE,IACA,OACA,aACA,SACA,SACA;EACA,KAAKA,MAAM;EACX,KAAKC,SAAS;EACd,KAAKC,eAAe;EACpB,KAAKC,WAAW;EAChB,KAAKC,WAAW;CAClB;CAEA,MAAM,MAAM;EACV,MAAM,EAAC,YAAY,YAAY,iBAAiB,aAAY,KAAKA;EAQjE,MAAM,mBAAmB,KAAK,MAAO,aAAa,IAAK,CAAC;EACxD,MAAM,gBACJ,mBACA,KAAK,MAAM,KAAK,OAAO,KAAK,aAAa,iBAAiB;EAC5D,KAAKJ,IAAI,OACP,uCAAuC,cAAc,kBAAkB,WAAW,IACpF;EACA,MAAM,KAAKK,OAAO,MAAM,aAAa;EAErC,OAAO,KAAKA,OAAO,UAAU,GAAG;GAC9B,MAAM,QAAQ,YAAY,IAAI;GAC9B,IAAI;IACF,MAAM,kBACJ,KAAKL,KACL,KAAKC,QACL,KAAKC,cACL;KAAC;KAAY;IAAe,GAC5B,KAAKC,UACL,aAAa,KAAA,IAAY,EAAC,SAAQ,IAAI,KAAA,CACxC;IACA,MAAM,UAAU,YAAY,IAAI,IAAI;IACpC,eAAe,IAAI,GAAG,EAAC,QAAQ,UAAS,CAAC;IACzC,mBAAmB,SAAS,SAAS,EAAC,QAAQ,UAAS,CAAC;IACxD,KAAKH,IAAI,OACP,kCAAkC,QAAQ,QAAQ,CAAC,EAAE,KACvD;GACF,SAAS,GAAG;IACV,MAAM,UAAU,YAAY,IAAI,IAAI;IACpC,eAAe,IAAI,GAAG,EAAC,QAAQ,QAAO,CAAC;IACvC,mBAAmB,SAAS,SAAS,EAAC,QAAQ,QAAO,CAAC;IACtD,KAAKA,IAAI,QACP,oCAAoC,QAAQ,QAAQ,CAAC,EAAE,MACvD,CACF;GACF;GACA,MAAM,KAAKK,OAAO,MAAM,UAAU;EACpC;CACF;CAEA,OAAsB;EACpB,KAAKA,OAAO,KAAK,KAAKL,GAAG;EACzB,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"shadow-sync-service.js","names":["#lc","#shard","#upstreamURI","#context","#options","#state"],"sources":["../../../../../../zero-cache/src/services/shadow-sync/shadow-sync-service.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {promiseVoid} from '../../../../shared/src/resolved-promises.ts';\nimport {\n getOrCreateCounter,\n getOrCreateLatencyHistogram,\n} from '../../observability/metrics.ts';\nimport type {ShardConfig} from '../../types/shards.ts';\nimport type {ServerContext} from '../change-source/pg/initial-sync.ts';\nimport {shadowInitialSync} from '../change-source/pg/initial-sync.ts';\nimport {RunningState} from '../running-state.ts';\nimport type {Service} from '../service.ts';\n\nfunction shadowSyncRuns() {\n return getOrCreateCounter(\n 'replication',\n 'shadow-sync-runs',\n 'Number of shadow initial-sync runs, labeled by result.',\n );\n}\n\nfunction shadowSyncDuration() {\n return getOrCreateLatencyHistogram(\n 'replication',\n 'shadow-sync-duration',\n 'Wall-clock duration of a shadow initial-sync run, labeled by result.',\n );\n}\n\nexport type ShadowSyncOptions = {\n intervalMs: number;\n sampleRate: number;\n maxRowsPerTable: number;\n textCopy?: boolean | undefined;\n};\n\nexport class ShadowSyncService implements Service {\n readonly id = 'shadow-syncer';\n\n readonly #lc: LogContext;\n readonly #shard: ShardConfig;\n readonly #upstreamURI: string;\n readonly #context: ServerContext;\n readonly #options: ShadowSyncOptions;\n readonly #state = new RunningState('shadow-syncer');\n\n constructor(\n lc: LogContext,\n shard: ShardConfig,\n upstreamURI: string,\n context: ServerContext,\n options: ShadowSyncOptions,\n ) {\n this.#lc = lc;\n this.#shard = shard;\n this.#upstreamURI = upstreamURI;\n this.#context = context;\n this.#options = options;\n }\n\n async run() {\n const {intervalMs, sampleRate, maxRowsPerTable, textCopy} = this.#options;\n\n // Why: first run fires in [intervalMs * 2/3, intervalMs) — late enough\n // that shadow sync never fires immediately on task startup, but always\n // before one full interval elapses so the canary completes at least once\n // per task lifetime (the replication manager is restarted every ~24h).\n // The last third is randomized so a fleet-wide restart does not cause\n // every task to canary simultaneously.\n const minFirstRunDelay = Math.floor((intervalMs * 2) / 3);\n const firstRunDelay =\n minFirstRunDelay +\n Math.floor(Math.random() * (intervalMs - minFirstRunDelay));\n this.#lc.info?.(\n `shadow-syncer started; first run in ${firstRunDelay} ms, then every ${intervalMs} ms`,\n );\n await this.#state.sleep(firstRunDelay);\n\n while (this.#state.shouldRun()) {\n const start = performance.now();\n try {\n await shadowInitialSync(\n this.#lc,\n this.#shard,\n this.#upstreamURI,\n {sampleRate, maxRowsPerTable},\n this.#context,\n textCopy !== undefined ? {textCopy} : undefined,\n );\n const elapsed = performance.now() - start;\n shadowSyncRuns().add(1, {result: 'success'});\n shadowSyncDuration().recordMs(elapsed, {result: 'success'});\n this.#lc.info?.(\n `shadow initial-sync completed (${elapsed.toFixed(0)} ms)`,\n );\n } catch (e) {\n const elapsed = performance.now() - start;\n shadowSyncRuns().add(1, {result: 'error'});\n shadowSyncDuration().recordMs(elapsed, {result: 'error'});\n this.#lc.error?.(\n `shadow initial-sync failed after ${elapsed.toFixed(0)} ms`,\n e,\n );\n }\n await this.#state.sleep(intervalMs);\n }\n }\n\n stop(): Promise<void> {\n this.#state.stop(this.#lc);\n return promiseVoid;\n }\n}\n"],"mappings":";;;;;AAYA,SAAS,iBAAiB;CACxB,OAAO,mBACL,eACA,oBACA,wDACF;AACF;AAEA,SAAS,qBAAqB;CAC5B,OAAO,4BACL,eACA,wBACA,sEACF;AACF;AASA,IAAa,oBAAb,MAAkD;CAChD,KAAc;CAEd;CACA;CACA;CACA;CACA;CACA,SAAkB,IAAI,aAAa,eAAe;CAElD,YACE,IACA,OACA,aACA,SACA,SACA;EACA,KAAKA,MAAM;EACX,KAAKC,SAAS;EACd,KAAKC,eAAe;EACpB,KAAKC,WAAW;EAChB,KAAKC,WAAW;CAClB;CAEA,MAAM,MAAM;EACV,MAAM,EAAC,YAAY,YAAY,iBAAiB,aAAY,KAAKA;EAQjE,MAAM,mBAAmB,KAAK,MAAO,aAAa,IAAK,CAAC;EACxD,MAAM,gBACJ,mBACA,KAAK,MAAM,KAAK,OAAO,KAAK,aAAa,iBAAiB;EAC5D,KAAKJ,IAAI,OACP,uCAAuC,cAAc,kBAAkB,WAAW,IACpF;EACA,MAAM,KAAKK,OAAO,MAAM,aAAa;EAErC,OAAO,KAAKA,OAAO,UAAU,GAAG;GAC9B,MAAM,QAAQ,YAAY,IAAI;GAC9B,IAAI;IACF,MAAM,kBACJ,KAAKL,KACL,KAAKC,QACL,KAAKC,cACL;KAAC;KAAY;IAAe,GAC5B,KAAKC,UACL,aAAa,KAAA,IAAY,EAAC,SAAQ,IAAI,KAAA,CACxC;IACA,MAAM,UAAU,YAAY,IAAI,IAAI;IACpC,eAAe,EAAE,IAAI,GAAG,EAAC,QAAQ,UAAS,CAAC;IAC3C,mBAAmB,EAAE,SAAS,SAAS,EAAC,QAAQ,UAAS,CAAC;IAC1D,KAAKH,IAAI,OACP,kCAAkC,QAAQ,QAAQ,CAAC,EAAE,KACvD;GACF,SAAS,GAAG;IACV,MAAM,UAAU,YAAY,IAAI,IAAI;IACpC,eAAe,EAAE,IAAI,GAAG,EAAC,QAAQ,QAAO,CAAC;IACzC,mBAAmB,EAAE,SAAS,SAAS,EAAC,QAAQ,QAAO,CAAC;IACxD,KAAKA,IAAI,QACP,oCAAoC,QAAQ,QAAQ,CAAC,EAAE,MACvD,CACF;GACF;GACA,MAAM,KAAKK,OAAO,MAAM,UAAU;EACpC;CACF;CAEA,OAAsB;EACpB,KAAKA,OAAO,KAAK,KAAKL,GAAG;EACzB,OAAO;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"cvr-store.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/cvr-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cvr-store.d.ts","sourceRoot":"","sources":["../../../../../../zero-cache/src/services/view-syncer/cvr-store.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ import { DEFAULT_TTL_MS, clampTTL } from "../../../../zql/src/query/ttl.js";
11
11
  import { cvrSchema } from "../../types/shards.js";
12
12
  import { startAsyncSpan } from "../../../../otel/src/span.js";
13
13
  import { version } from "../../../../otel/src/version.js";
14
+ import { getOrCreateCounter, getOrCreateLatencyHistogram } from "../../observability/metrics.js";
14
15
  import { rowIDString } from "../../types/row-key.js";
15
16
  import { READONLY, READ_COMMITTED } from "../../db/mode-enum.js";
16
17
  import { runTx } from "../../db/run-transaction.js";
@@ -26,6 +27,9 @@ import { RowRecordCache } from "./row-record-cache.js";
26
27
  import { trace } from "@opentelemetry/api";
27
28
  //#region ../zero-cache/src/services/view-syncer/cvr-store.ts
28
29
  var flushCounter = 0;
30
+ var RESULT_ATTRIBUTE = "result";
31
+ var ERROR_KIND_ATTRIBUTE = "error.kind";
32
+ var CVR_FLUSH_TYPE_ATTRIBUTE = "flush.type";
29
33
  /**
30
34
  * Convert TTL/timestamp values for both old (seconds-based) and new (ms-based) columns.
31
35
  * Old columns: inactivatedAt (TIMESTAMPTZ), ttl (INTERVAL) - need conversion ms->seconds
@@ -89,6 +93,9 @@ var CVRStore = class {
89
93
  #pendingRowRecordUpdates = new CustomKeyMap(rowIDString);
90
94
  #forceUpdates = new CustomKeySet(rowIDString);
91
95
  #rowCache;
96
+ #cvrLoads = getOrCreateCounter("sync", "cvr.load_attempts", "CVR load attempts, labeled by result.");
97
+ #cvrLoadTime = getOrCreateLatencyHistogram("sync", "cvr.load_duration", "Time to load a CVR.");
98
+ #cvrFlushes = getOrCreateCounter("sync", "cvr.flush_attempts", "CVR flush attempts, labeled by result and flush.type.");
92
99
  #loadAttemptIntervalMs;
93
100
  #maxLoadAttempts;
94
101
  #rowCount = 0;
@@ -116,22 +123,36 @@ var CVRStore = class {
116
123
  } : fields);
117
124
  }
118
125
  load(lc, lastConnectTime) {
126
+ const start = performance.now();
119
127
  return startAsyncSpan(tracer, "cvr.load", async () => {
120
- let err;
121
- for (let i = 0; i < this.#maxLoadAttempts; i++) {
122
- if (i > 0) await sleep(this.#loadAttemptIntervalMs);
123
- const result = await this.#load(lc, lastConnectTime);
124
- if (result instanceof RowsVersionBehindError) {
125
- lc.info?.(`attempt ${i + 1}: ${String(result)}`);
126
- err = result;
127
- continue;
128
+ try {
129
+ let err;
130
+ for (let i = 0; i < this.#maxLoadAttempts; i++) {
131
+ if (i > 0) await sleep(this.#loadAttemptIntervalMs);
132
+ const result = await this.#load(lc, lastConnectTime);
133
+ if (result instanceof RowsVersionBehindError) {
134
+ lc.info?.(`attempt ${i + 1}: ${String(result)}`);
135
+ err = result;
136
+ continue;
137
+ }
138
+ this.#recordLoad(performance.now() - start, { [RESULT_ATTRIBUTE]: "success" });
139
+ return result;
128
140
  }
129
- return result;
141
+ assert(err, "Expected error to be set after retry loop exhausted");
142
+ throw new ClientNotFoundError(`max attempts exceeded waiting for CVR@${err.cvrVersion} to catch up from ${err.rowsVersion}`);
143
+ } catch (e) {
144
+ this.#recordLoad(performance.now() - start, {
145
+ [RESULT_ATTRIBUTE]: "error",
146
+ [ERROR_KIND_ATTRIBUTE]: cvrErrorKind(e)
147
+ });
148
+ throw e;
130
149
  }
131
- assert(err, "Expected error to be set after retry loop exhausted");
132
- throw new ClientNotFoundError(`max attempts exceeded waiting for CVR@${err.cvrVersion} to catch up from ${err.rowsVersion}`);
133
150
  });
134
151
  }
152
+ #recordLoad(elapsedMs, attributes) {
153
+ this.#cvrLoads.add(1, attributes);
154
+ this.#cvrLoadTime.recordMs(elapsedMs, attributes);
155
+ }
135
156
  async #load(lc, lastConnectTime) {
136
157
  const start = Date.now();
137
158
  const id = this.#id;
@@ -744,8 +765,17 @@ var CVRStore = class {
744
765
  lc.info?.(`flushed cvr@${versionString(cvr.version)} ${JSON.stringify(stats)} in (${elapsed} ms)`);
745
766
  this.#rowCache.recordSyncFlushStats(stats, elapsed);
746
767
  }
768
+ this.#cvrFlushes.add(1, {
769
+ [RESULT_ATTRIBUTE]: "success",
770
+ [CVR_FLUSH_TYPE_ATTRIBUTE]: stats ? "sync" : "noop"
771
+ });
747
772
  return stats;
748
773
  } catch (e) {
774
+ this.#cvrFlushes.add(1, {
775
+ [RESULT_ATTRIBUTE]: "error",
776
+ [CVR_FLUSH_TYPE_ATTRIBUTE]: "sync",
777
+ [ERROR_KIND_ATTRIBUTE]: cvrErrorKind(e)
778
+ });
749
779
  this.#rowCache.clear();
750
780
  throw e;
751
781
  } finally {
@@ -854,6 +884,13 @@ var InvalidClientSchemaError = class extends ProtocolErrorWithLevel {
854
884
  }, "warn", { cause });
855
885
  }
856
886
  };
887
+ function cvrErrorKind(e) {
888
+ if (e instanceof ClientNotFoundError) return "client_not_found";
889
+ if (e instanceof ConcurrentModificationException) return "concurrent_modification";
890
+ if (e instanceof OwnershipError) return "ownership";
891
+ if (e instanceof InvalidClientSchemaError) return "invalid_client_schema";
892
+ return "error";
893
+ }
857
894
  var RowsVersionBehindError = class extends Error {
858
895
  name = "RowsVersionBehindError";
859
896
  cvrVersion;