@checkstack/backend 0.8.0 → 0.8.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @checkstack/backend
2
2
 
3
+ ## 0.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 2a749d3: fix: run afterPluginsReady in topological order; merge daily rollups on conflict
8
+
9
+ Two resilience fixes for the dependency chain:
10
+
11
+ 1. **Plugin loader**: Phase 3 (`afterPluginsReady`) now iterates plugins
12
+ in the same topologically-sorted order as Phase 2 (`init`). Previously
13
+ it iterated `pendingInits` in registration order, which raced
14
+ subscription-spec dependencies — catalog's afterPluginsReady registers
15
+ `catalog.system` and `catalog.group` notification targets, and emitting
16
+ plugins (incident, maintenance, …) call `registerSubscriptionSpec`
17
+ against those targets in their own afterPluginsReady. With registration
18
+ order, an emitter could run before catalog and hit
19
+ `Target type catalog.group is not registered`. Sorted order encodes
20
+ the dependency via `spec.target.ownerPlugin`, so the emitter now
21
+ always runs after the target owner.
22
+
23
+ 2. **Healthcheck retention job**: the daily rollup now upserts
24
+ `health_check_aggregates` with `ON CONFLICT DO UPDATE` instead of a
25
+ plain insert. Previously, late-arriving hourly aggregates (e.g. from
26
+ a satellite that was offline when the prior rollup ran) would crash
27
+ the rollup with a unique-constraint violation on
28
+ `(configuration_id, system_id, bucket_start, bucket_size, source_id)`.
29
+ The merge sums counts and folds min/max/p95 into the existing daily
30
+ row.
31
+
3
32
  ## 0.8.0
4
33
 
5
34
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/backend",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "checkstack": {
5
5
  "type": "backend"
6
6
  },
@@ -515,7 +515,15 @@ export async function loadPlugins({
515
515
  );
516
516
  }
517
517
  }
518
- for (const p of pendingInits) {
518
+ // Run afterPluginsReady in topologically-sorted order, matching Phase
519
+ // 2 init order. Iterating `pendingInits` directly would use registration
520
+ // order, which races dependency chains: e.g. catalog's
521
+ // afterPluginsReady registers `catalog.group` as a notification target,
522
+ // and emitting plugins' afterPluginsReady call `registerSubscriptionSpec`
523
+ // against it — so the emitters MUST run after catalog. Topo order
524
+ // already encodes this dependency (via spec.target.ownerPlugin).
525
+ for (const id of sortedIds) {
526
+ const p = pendingInits.find((x) => x.metadata.pluginId === id)!;
519
527
  if (p.afterPluginsReady) {
520
528
  try {
521
529
  const resolvedDeps: Record<string, unknown> = {};