signalk-questdb 1.8.4 → 1.9.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.
Files changed (51) hide show
  1. package/README.md +22 -7
  2. package/dist/api-contract.d.ts +29 -9
  3. package/dist/configpanel/responses.d.ts +1 -11
  4. package/dist/configpanel/responses.js +0 -19
  5. package/dist/configpanel/responses.js.map +1 -1
  6. package/dist/delta-routing.d.ts +55 -1
  7. package/dist/delta-routing.js +110 -1
  8. package/dist/delta-routing.js.map +1 -1
  9. package/dist/history-v1.d.ts +1 -0
  10. package/dist/history-v1.js +86 -35
  11. package/dist/history-v1.js.map +1 -1
  12. package/dist/history-v2.d.ts +2 -0
  13. package/dist/history-v2.js +30 -16
  14. package/dist/history-v2.js.map +1 -1
  15. package/dist/ilp-writer.d.ts +3 -3
  16. package/dist/ilp-writer.js +12 -6
  17. package/dist/ilp-writer.js.map +1 -1
  18. package/dist/index.js +166 -25
  19. package/dist/index.js.map +1 -1
  20. package/dist/query-client.d.ts +2 -2
  21. package/dist/query-client.js +50 -6
  22. package/dist/query-client.js.map +1 -1
  23. package/dist/questdb-endpoint.d.ts +14 -0
  24. package/dist/questdb-endpoint.js.map +1 -1
  25. package/dist/restore.js +107 -16
  26. package/dist/restore.js.map +1 -1
  27. package/dist/test/configpanel-responses.test.js +1 -64
  28. package/dist/test/configpanel-responses.test.js.map +1 -1
  29. package/dist/test/delta-routing.test.js +203 -19
  30. package/dist/test/delta-routing.test.js.map +1 -1
  31. package/dist/test/history-v1.test.js +169 -0
  32. package/dist/test/history-v1.test.js.map +1 -1
  33. package/dist/test/history-v2.test.js +153 -0
  34. package/dist/test/history-v2.test.js.map +1 -1
  35. package/dist/test/ilp-writer.test.js +29 -0
  36. package/dist/test/ilp-writer.test.js.map +1 -1
  37. package/dist/test/query-client.test.js +63 -0
  38. package/dist/test/query-client.test.js.map +1 -1
  39. package/dist/test/restore.test.js +107 -0
  40. package/dist/test/restore.test.js.map +1 -1
  41. package/package.json +2 -1
  42. package/public/assets/PluginConfigurationPanel-Wr6ovJk-.js +9 -0
  43. package/public/assets/_virtual_mf-localSharedImportMap___mfe_internal__signalk_questdb__mf_owner__1-I2PEpnTA.js +1 -0
  44. package/public/assets/hostInit-CUx4ptQ-.js +1 -0
  45. package/public/assets/{index-B5SQqvFM.js → index-CyAGi7fm.js} +1 -1
  46. package/public/assets/virtualExposes-pKhk7rm8.js +1 -0
  47. package/public/remoteEntry.js +1 -1
  48. package/public/assets/PluginConfigurationPanel-BUIFH2d0.js +0 -9
  49. package/public/assets/_virtual_mf-localSharedImportMap___mfe_internal__signalk_questdb__mf_owner__1-CVM43rXb.js +0 -1
  50. package/public/assets/hostInit-BK1oa2Z9.js +0 -1
  51. package/public/assets/virtualExposes-BkvbtHi8.js +0 -1
package/README.md CHANGED
@@ -34,7 +34,7 @@ The plugin embeds a React config panel in the Signal K Admin UI showing:
34
34
  - **Image Version** -- dropdown with latest, pre-releases, and last 3 stable releases
35
35
  - **Connection** -- managed container toggle, host/ports, PostgreSQL port for Grafana
36
36
  - **Recording** -- record self, record AIS targets, startup restore, console webapp, retention days
37
- - **Path filtering** (collapsible) -- exclude or include-only paths with glob patterns (e.g. exclude `notifications.*`); empty by default, so everything is recorded
37
+ - **Path filtering** (collapsible) -- exclude or include-only paths with glob patterns
38
38
  - **Compression** (collapsible) -- LZ4/ZSTD codec selection for on-disk storage
39
39
  - **InfluxDB Migration** (collapsible) -- auto-detect with manual URL for remote instances
40
40
  - **Data Export** (collapsible) -- date range picker, Parquet/CSV format, download button
@@ -44,11 +44,11 @@ The plugin embeds a React config panel in the Signal K Admin UI showing:
44
44
 
45
45
  Three tables, all with WAL mode, daily partitioning, and deduplication:
46
46
 
47
- | Table | Purpose | Columns |
48
- | ------------------ | -------------- | ---------------------------------------------------------------- |
49
- | `signalk` | Numeric values | `ts`, `path` (SYMBOL), `context` (SYMBOL), `value` (DOUBLE) |
50
- | `signalk_str` | String values | `ts`, `path` (SYMBOL), `context` (SYMBOL), `value_str` (VARCHAR) |
51
- | `signalk_position` | Positions | `ts`, `context` (SYMBOL), `lat` (DOUBLE), `lon` (DOUBLE) |
47
+ | Table | Purpose | Columns |
48
+ | ------------------ | -------------- | ---------------------------------------------------------------------------------------------------------- |
49
+ | `signalk` | Numeric values | `ts`, `path` (SYMBOL), `context` (SYMBOL), `source` (SYMBOL), `value` (DOUBLE) |
50
+ | `signalk_str` | String values | `ts`, `path` (SYMBOL), `context` (SYMBOL), `source` (SYMBOL), `value_str` (VARCHAR), `value_kind` (SYMBOL) |
51
+ | `signalk_position` | Positions | `ts`, `context` (SYMBOL), `source` (SYMBOL), `lat` (DOUBLE), `lon` (DOUBLE) |
52
52
 
53
53
  `ts` is the **server receive time**, not the timestamp a source claims. Marine
54
54
  sources carry independent clocks, and storing their timestamps makes commits
@@ -57,6 +57,11 @@ land out of order — QuestDB then rewrites partition tails on every merge
57
57
  append-only; the millisecond difference is far below the sampling resolution,
58
58
  and a device with a broken clock gets more accurate history, not less.
59
59
 
60
+ `source` is the delta's sourceRef — which receiver produced the row. Two GPS
61
+ units feeding the same server interleave in storage, and without the column a
62
+ track drawn from history zigzags between them. Rows recorded before the column
63
+ existed have `source` null; they replay unattributed and cannot be filtered.
64
+
60
65
  ## History API
61
66
 
62
67
  ### v2 (REST -- `/signalk/v2/api/history/`)
@@ -80,9 +85,19 @@ Query example:
80
85
  GET /signalk/v2/api/history/values?paths=navigation.speedOverGround&duration=PT1H&resolution=60
81
86
  ```
82
87
 
88
+ Append `|<sourceRef>` to a path to read one source's rows only (server 2.29+,
89
+ [signalk-server#2737](https://github.com/SignalK/signalk-server/pull/2737)).
90
+ The same path may appear once per source, giving one column per receiver:
91
+
92
+ ```
93
+ GET /signalk/v2/api/history/values?paths=navigation.position|gps.main,navigation.position|gps.backup&duration=PT1H
94
+ ```
95
+
96
+ Without a sourceRef a path returns all sources mixed, as before.
97
+
83
98
  ### v1 (WebSocket playback)
84
99
 
85
- Registered via `app.registerHistoryProvider()`. Supports playback at configurable speed multipliers using chunked reads from QuestDB.
100
+ Registered via `app.registerHistoryProvider()`. Supports playback at configurable speed multipliers using chunked reads from QuestDB. Replayed updates carry the recorded sourceRef as `$source`, one update per source, so consumers see the same attribution the live stream had.
86
101
 
87
102
  ## REST Endpoints
88
103
 
@@ -1,3 +1,4 @@
1
+ import type { UlimitClamp } from "signalk-container-helper";
1
2
  import type { MaxMapCountStatus } from "./host-limits.js";
2
3
  import type { SkipPlan, SuspendedTable } from "./wal-monitor.js";
3
4
  /**
@@ -11,16 +12,15 @@ export interface ApiError {
11
12
  message?: string;
12
13
  }
13
14
  /**
14
- * Mirror of signalk-container's `UlimitClamp` event, redeclared (not
15
- * imported) for the same reason index.ts redeclares it: signalk-container is
16
- * an optional peer reached through globalThis, so there is no type to import.
15
+ * signalk-container's `UlimitClamp` event, re-exported under the name the
16
+ * API responses use.
17
+ *
18
+ * `import type` is load-bearing: this file is shared with the browser panel,
19
+ * and the helper's main entry carries ~19KB of Node-side runtime code. A
20
+ * value import would drag all of it into the federated bundle. The type-only
21
+ * form is erased at compile time, so nothing ships.
17
22
  */
18
- export interface UlimitClampStatus {
19
- ulimit: string;
20
- requested: number;
21
- granted: number;
22
- reason: string;
23
- }
23
+ export type UlimitClampStatus = UlimitClamp;
24
24
  export type SuspendedTableStatus = SuspendedTable & {
25
25
  /** WAL monitor's verdict for the current stall point: "pending" | "failed". */
26
26
  autoResume: string | null;
@@ -51,6 +51,26 @@ export interface DbStatus extends ApiError {
51
51
  * display name gets an empty statusMessage and the count would be invisible.
52
52
  */
53
53
  restore?: RestoreStatus | null;
54
+ /**
55
+ * Paths seen carrying a value no table can hold — arrays, or objects nested
56
+ * deeper than the one level that gets flattened. Absent when nothing has
57
+ * been dropped. Surfaced because the previous behaviour was to drop them
58
+ * silently, which is how attitude went unrecorded unnoticed (issue #128).
59
+ */
60
+ unstorable?: UnstorableStatus | null;
61
+ }
62
+ /** Values encountered that cannot be represented in any table. */
63
+ export interface UnstorableStatus {
64
+ /**
65
+ * Distinct paths dropped since the plugin started. A LOWER BOUND when
66
+ * `truncated` is set: tracking is capped, because Signal K paths embed
67
+ * instance and vessel identifiers and so are not a bounded vocabulary.
68
+ */
69
+ paths: number;
70
+ /** True once the cap was hit and further distinct paths stopped being kept. */
71
+ truncated: boolean;
72
+ /** A sample of those paths, for identifying them without reading logs. */
73
+ examples: string[];
54
74
  }
55
75
  /** Startup-restore outcome, shown on the config panel. */
56
76
  export interface RestoreStatus {
@@ -1,14 +1,4 @@
1
- import type { MigrationSource, QuestdbVersion } from "../api-contract.js";
2
- /**
3
- * GET /api/versions returns an array of releases. Anything else becomes an
4
- * empty list, and malformed members are dropped: the version dropdown is
5
- * then short or empty rather than the panel being gone.
6
- *
7
- * Members are validated, not just the array — `versions.filter(v =>
8
- * !v.prerelease)` runs during render, so a single null element is as fatal
9
- * as a non-array body.
10
- */
11
- export declare function toVersionList(body: unknown): QuestdbVersion[];
1
+ import type { MigrationSource } from "../api-contract.js";
12
2
  /**
13
3
  * GET /api/migration/detect returns `{ sources: [...] }`. A body without it
14
4
  * means "nothing detected", which is also what an empty array means — so the
@@ -9,25 +9,6 @@
9
9
  //
10
10
  // These helpers keep the "trust but verify" boundary in one testable place.
11
11
  const isRecord = (v) => typeof v === "object" && v !== null;
12
- /**
13
- * GET /api/versions returns an array of releases. Anything else becomes an
14
- * empty list, and malformed members are dropped: the version dropdown is
15
- * then short or empty rather than the panel being gone.
16
- *
17
- * Members are validated, not just the array — `versions.filter(v =>
18
- * !v.prerelease)` runs during render, so a single null element is as fatal
19
- * as a non-array body.
20
- */
21
- export function toVersionList(body) {
22
- if (!Array.isArray(body))
23
- return [];
24
- return body.filter((v) => isRecord(v) &&
25
- typeof v.tag === "string" &&
26
- // Not merely cosmetic: the two filters below partition on this, so a
27
- // missing or non-boolean value would list a pre-release as stable —
28
- // and the stable list is what the version dropdown defaults to.
29
- typeof v.prerelease === "boolean");
30
- }
31
12
  /**
32
13
  * GET /api/migration/detect returns `{ sources: [...] }`. A body without it
33
14
  * means "nothing detected", which is also what an empty array means — so the
@@ -1 +1 @@
1
- {"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/configpanel/responses.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,wEAAwE;AACxE,4EAA4E;AAC5E,uEAAuE;AACvE,EAAE;AACF,4EAA4E;AAI5E,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAgC,EAAE,CAC5D,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC;AAEtC;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,IAAI,CAAC,MAAM,CAChB,CAAC,CAAC,EAAuB,EAAE,CACzB,QAAQ,CAAC,CAAC,CAAC;QACX,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;QACzB,qEAAqE;QACrE,oEAAoE;QACpE,gEAAgE;QAChE,OAAO,CAAC,CAAC,UAAU,KAAK,SAAS,CACpC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAa;IAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO,CAAC,MAAM,CACnB,CAAC,CAAC,EAAwB,EAAE,CAC1B,QAAQ,CAAC,CAAC,CAAC;QACX,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;QACzB,iEAAiE;QACjE,kEAAkE;QAClE,iEAAiE;QACjE,sDAAsD;QACtD,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAC5B,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAC7D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/configpanel/responses.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,wEAAwE;AACxE,4EAA4E;AAC5E,uEAAuE;AACvE,EAAE;AACF,4EAA4E;AAI5E,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAgC,EAAE,CAC5D,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAa;IAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO,CAAC,MAAM,CACnB,CAAC,CAAC,EAAwB,EAAE,CAC1B,QAAQ,CAAC,CAAC,CAAC;QACX,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;QACzB,iEAAiE;QACjE,kEAAkE;QAClE,iEAAiE;QACjE,sDAAsD;QACtD,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAC5B,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAC7D,CAAC;AACJ,CAAC"}
@@ -1,3 +1,57 @@
1
- export type DeltaRoute = "number" | "string" | "boolean" | "position" | null;
1
+ export type DeltaRoute = "number" | "string" | "boolean" | "position" | "flatten" | null;
2
+ /** One scalar leaf pulled out of an object value, ready to record. */
3
+ export interface FlattenedLeaf {
4
+ /** Parent path plus the key, e.g. `navigation.attitude.roll`. */
5
+ path: string;
6
+ value: number | string | boolean;
7
+ }
8
+ /**
9
+ * Remembers which paths carried a value no table can hold, so the drop can be
10
+ * reported instead of happening in silence — the underlying bug behind #128.
11
+ *
12
+ * Capped, because the path vocabulary is NOT bounded: paths embed instance
13
+ * identifiers (`watermaker.0.*`) and notifications embed per-vessel ones, so
14
+ * an unstorable shape on a busy AIS stream would grow an uncapped set for the
15
+ * lifetime of the process. Past the cap the count still rises but no new path
16
+ * is retained, and `truncated` marks the count as a lower bound rather than
17
+ * letting it read as exact.
18
+ *
19
+ * Deliberately does no logging: `note()` runs per delta on a stream carrying
20
+ * 100+ values/sec, and building a message string there costs whether or not
21
+ * debug is enabled.
22
+ */
23
+ export declare class UnstorableTracker {
24
+ private readonly cap;
25
+ private readonly paths;
26
+ private capped;
27
+ constructor(cap?: number);
28
+ /** Records a path. Cheap and idempotent; safe to call per delta. */
29
+ note(path: string): void;
30
+ get size(): number;
31
+ get truncated(): boolean;
32
+ examples(limit: number): string[];
33
+ clear(): void;
34
+ }
2
35
  export declare function extractVesselName(path: string, value: unknown): string | null;
3
36
  export declare function routeDeltaValue(path: string, value: unknown): DeltaRoute;
37
+ /**
38
+ * Scalar leaves of an object value, as dotted paths.
39
+ *
40
+ * navigation.attitude {roll: 0.02, yaw: 1.57}
41
+ * -> navigation.attitude.roll 0.02
42
+ * -> navigation.attitude.yaw 1.57
43
+ *
44
+ * **One level deep, deliberately.** That covers attitude and effectively every
45
+ * real Signal K object, while a recursive walk would happily write out whole
46
+ * nested payloads (notifications, resource documents) that nobody asked to
47
+ * record. A nested object is therefore skipped, not descended into — and
48
+ * reported, so it is not another silent drop.
49
+ *
50
+ * The leaves are ordinary scalar paths, which is what makes this cheap: no
51
+ * schema change, and dedup, retention, sampling, path filtering and both
52
+ * history APIs apply to them unchanged.
53
+ */
54
+ export declare function flattenObjectValue(path: string, value: unknown): {
55
+ leaves: FlattenedLeaf[];
56
+ skipped: string[];
57
+ };
@@ -1,3 +1,49 @@
1
+ /**
2
+ * Remembers which paths carried a value no table can hold, so the drop can be
3
+ * reported instead of happening in silence — the underlying bug behind #128.
4
+ *
5
+ * Capped, because the path vocabulary is NOT bounded: paths embed instance
6
+ * identifiers (`watermaker.0.*`) and notifications embed per-vessel ones, so
7
+ * an unstorable shape on a busy AIS stream would grow an uncapped set for the
8
+ * lifetime of the process. Past the cap the count still rises but no new path
9
+ * is retained, and `truncated` marks the count as a lower bound rather than
10
+ * letting it read as exact.
11
+ *
12
+ * Deliberately does no logging: `note()` runs per delta on a stream carrying
13
+ * 100+ values/sec, and building a message string there costs whether or not
14
+ * debug is enabled.
15
+ */
16
+ export class UnstorableTracker {
17
+ cap;
18
+ paths = new Set();
19
+ capped = false;
20
+ constructor(cap = 50) {
21
+ this.cap = cap;
22
+ }
23
+ /** Records a path. Cheap and idempotent; safe to call per delta. */
24
+ note(path) {
25
+ if (this.paths.has(path))
26
+ return;
27
+ if (this.paths.size >= this.cap) {
28
+ this.capped = true;
29
+ return;
30
+ }
31
+ this.paths.add(path);
32
+ }
33
+ get size() {
34
+ return this.paths.size;
35
+ }
36
+ get truncated() {
37
+ return this.capped;
38
+ }
39
+ examples(limit) {
40
+ return [...this.paths].slice(0, limit);
41
+ }
42
+ clear() {
43
+ this.paths.clear();
44
+ this.capped = false;
45
+ }
46
+ }
1
47
  // Static vessel identity arrives as EMPTY-path object deltas —
2
48
  // `{path: "", value: {name: "..."}}` is how AIS static reports reach the
3
49
  // server, and the exact shape Freeboard reads names from. These never make
@@ -13,8 +59,15 @@ export function extractVesselName(path, value) {
13
59
  return typeof name === "string" && name.trim() !== "" ? name : null;
14
60
  }
15
61
  export function routeDeltaValue(path, value) {
62
+ // NaN and ±Infinity have no ILP representation. QuestDB does NOT reject
63
+ // them — verified against a live instance, `value=NaN` is accepted and
64
+ // stored — so an unguarded sensor fault silently poisons the numeric
65
+ // column, and every aggregate over that path afterwards. A source
66
+ // reporting a non-finite number is reporting "no reading", which is what
67
+ // recording nothing means. flattenObjectValue already applied this to
68
+ // leaves; the top-level path has to agree.
16
69
  if (typeof value === "number")
17
- return "number";
70
+ return Number.isFinite(value) ? "number" : null;
18
71
  if (typeof value === "string")
19
72
  return "string";
20
73
  // Booleans are everywhere in Signal K — switch and relay states, pump and
@@ -34,6 +87,62 @@ export function routeDeltaValue(path, value) {
34
87
  Number.isFinite(value.latitude) &&
35
88
  Number.isFinite(value.longitude))
36
89
  return "position";
90
+ // Any other non-null, non-array object: record its scalar leaves
91
+ // individually. Arrays are excluded deliberately — their indices are not
92
+ // stable identities, so `foo.0` would silently mean a different thing from
93
+ // one delta to the next.
94
+ if (value !== null && typeof value === "object" && !Array.isArray(value))
95
+ return "flatten";
37
96
  return null;
38
97
  }
98
+ /**
99
+ * Scalar leaves of an object value, as dotted paths.
100
+ *
101
+ * navigation.attitude {roll: 0.02, yaw: 1.57}
102
+ * -> navigation.attitude.roll 0.02
103
+ * -> navigation.attitude.yaw 1.57
104
+ *
105
+ * **One level deep, deliberately.** That covers attitude and effectively every
106
+ * real Signal K object, while a recursive walk would happily write out whole
107
+ * nested payloads (notifications, resource documents) that nobody asked to
108
+ * record. A nested object is therefore skipped, not descended into — and
109
+ * reported, so it is not another silent drop.
110
+ *
111
+ * The leaves are ordinary scalar paths, which is what makes this cheap: no
112
+ * schema change, and dedup, retention, sampling, path filtering and both
113
+ * history APIs apply to them unchanged.
114
+ */
115
+ export function flattenObjectValue(path, value) {
116
+ const leaves = [];
117
+ const skipped = [];
118
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
119
+ return { leaves, skipped };
120
+ }
121
+ // An empty parent would build ".name" — a leading-dot path that matches no
122
+ // Signal K path and no filter pattern. The recorder already returns before
123
+ // reaching here for path "" (that shape is the AIS static report, handled
124
+ // by extractVesselName), so this is belt-and-braces: the function must not
125
+ // depend on a caller's guard to avoid emitting a malformed path.
126
+ if (path === "")
127
+ return { leaves, skipped };
128
+ for (const [key, leaf] of Object.entries(value)) {
129
+ const leafPath = `${path}.${key}`;
130
+ if (typeof leaf === "number") {
131
+ // NaN and ±Infinity have no ILP representation and would poison the
132
+ // column; a sensor reporting them is reporting "no reading".
133
+ if (Number.isFinite(leaf))
134
+ leaves.push({ path: leafPath, value: leaf });
135
+ else
136
+ skipped.push(leafPath);
137
+ }
138
+ else if (typeof leaf === "string" || typeof leaf === "boolean") {
139
+ leaves.push({ path: leafPath, value: leaf });
140
+ }
141
+ else {
142
+ // Nested object, array, null or undefined.
143
+ skipped.push(leafPath);
144
+ }
145
+ }
146
+ return { leaves, skipped };
147
+ }
39
148
  //# sourceMappingURL=delta-routing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"delta-routing.js","sourceRoot":"","sources":["../src/delta-routing.ts"],"names":[],"mappings":"AAUA,+DAA+D;AAC/D,yEAAyE;AACzE,2EAA2E;AAC3E,sEAAsE;AACtE,wEAAwE;AACxE,uBAAuB;AACvB,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,KAAc;IAC5D,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;IAChD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAc;IAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC/C,0EAA0E;IAC1E,yEAAyE;IACzE,iEAAiE;IACjE,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,qDAAqD;IACrD,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACjD,IACE,IAAI,KAAK,qBAAqB;QAC9B,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,UAAU,IAAI,KAAK;QACnB,WAAW,IAAI,KAAK;QACpB,MAAM,CAAC,QAAQ,CAAE,KAA+B,CAAC,QAAQ,CAAC;QAC1D,MAAM,CAAC,QAAQ,CAAE,KAAgC,CAAC,SAAS,CAAC;QAE5D,OAAO,UAAU,CAAC;IACpB,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"delta-routing.js","sourceRoot":"","sources":["../src/delta-routing.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ interface Delta {
8
8
  context: string;
9
9
  updates: {
10
10
  timestamp: string;
11
+ $source?: string;
11
12
  values: {
12
13
  path: string;
13
14
  value: unknown;
@@ -10,8 +10,16 @@ import { validateTimestamp } from "./query-client.js";
10
10
  // branch — the snapshot's LATEST ON clause. Keeping every branch here is the
11
11
  // point: the snapshot query used to re-implement these by hand and drifted,
12
12
  // silently replaying booleans as text on that path only.
13
- function numBranch(where, tail = "") {
14
- return (`SELECT ts, path, context, CAST(value AS STRING) valuetext, ` +
13
+ // `withSource: false` degrades like `withKind: false` below: the source
14
+ // column is a later migration still, so a read racing ensureTables() (or an
15
+ // external QuestDB the plugin does not own) replays unattributed rather than
16
+ // not at all.
17
+ function sourceCol(withSource) {
18
+ return withSource ? `CAST(source AS STRING)` : `CAST(NULL AS STRING)`;
19
+ }
20
+ function numBranch(where, withSource, tail = "") {
21
+ return (`SELECT ts, path, context, ${sourceCol(withSource)} source, ` +
22
+ `CAST(value AS STRING) valuetext, ` +
15
23
  `'number' kind FROM signalk WHERE ${where}${tail}`);
16
24
  }
17
25
  // `withKind: false` degrades to the pre-migration shape. ensureTables() adds
@@ -20,26 +28,33 @@ function numBranch(where, tail = "") {
20
28
  // union with "Invalid column: value_kind" — turning a missing type tag into
21
29
  // no history at all. The NULL is cast so the union's column type is stated
22
30
  // rather than inferred.
23
- function strBranch(where, withKind, tail = "") {
31
+ function strBranch(where, withKind, withSource, tail = "") {
24
32
  const kind = withKind ? `CAST(value_kind AS STRING)` : `CAST(NULL AS STRING)`;
25
- return (`SELECT ts, path, context, value_str valuetext, ${kind} kind ` +
33
+ return (`SELECT ts, path, context, ${sourceCol(withSource)} source, ` +
34
+ `value_str valuetext, ${kind} kind ` +
26
35
  `FROM signalk_str WHERE ${where}${tail}`);
27
36
  }
28
37
  // The track table has no path column, so the path is supplied as a literal.
29
- function posBranch(where, tail = "") {
38
+ function posBranch(where, withSource, tail = "") {
30
39
  return (`SELECT ts, 'navigation.position' path, context, ` +
40
+ `${sourceCol(withSource)} source, ` +
31
41
  `concat(CAST(lat AS STRING), ',', CAST(lon AS STRING)) valuetext, ` +
32
42
  `'position' kind FROM signalk_position WHERE ${where}${tail}`);
33
43
  }
34
- function unionValueRowsSQL(where, orderAndLimit, withKind = true) {
35
- return (`${numBranch(where)} UNION ALL ` +
36
- `${strBranch(where, withKind)} UNION ALL ` +
37
- `${posBranch(where)} ${orderAndLimit}`);
44
+ function unionValueRowsSQL(where, orderAndLimit, withKind = true, withSource = true) {
45
+ return (`${numBranch(where, withSource)} UNION ALL ` +
46
+ `${strBranch(where, withKind, withSource)} UNION ALL ` +
47
+ `${posBranch(where, withSource)} ${orderAndLimit}`);
38
48
  }
39
49
  // True for the error QuestDB returns when value_kind has not been added yet.
40
50
  function isMissingKindColumn(err) {
41
51
  return /Invalid column:\s*value_kind/i.test(err instanceof Error ? err.message : String(err));
42
52
  }
53
+ // Same, for the source column (a later migration than value_kind, so each
54
+ // can be missing independently of the other).
55
+ function isMissingSourceColumn(err) {
56
+ return /Invalid column:\s*source/i.test(err instanceof Error ? err.message : String(err));
57
+ }
43
58
  // Turn a unified row back into the value a Signal K delta carries. Numbers
44
59
  // must not stay strings (consumers do arithmetic on them), positions must be
45
60
  // objects again, and a value recorded as a boolean must replay as a boolean.
@@ -73,10 +88,16 @@ function decodeValue(row) {
73
88
  }
74
89
  }
75
90
  function groupRowsIntoDeltas(rows) {
91
+ // Grouped by (ts, context, source): mixing two sources' rows into one
92
+ // update would force a single $source label onto both, so each source
93
+ // gets its own update — exactly how the live deltas arrived. Rows with no
94
+ // recorded source (pre-migration data) group under `undefined` and replay
95
+ // without a $source, as before.
76
96
  const byTimestamp = new Map();
77
97
  for (const row of rows) {
78
98
  const ts = row.ts;
79
99
  const context = row.context || "self";
100
+ const source = typeof row.source === "string" ? row.source : undefined;
80
101
  const path = row.path;
81
102
  // Both call sites query the unified shape, so every row carries
82
103
  // `valuetext` + `kind` for decodeValue to reconstruct.
@@ -84,27 +105,34 @@ function groupRowsIntoDeltas(rows) {
84
105
  if (!byTimestamp.has(ts)) {
85
106
  byTimestamp.set(ts, new Map());
86
107
  }
87
- const byContext = byTimestamp.get(ts);
88
- if (!byContext.has(context)) {
89
- byContext.set(context, []);
108
+ const byGroup = byTimestamp.get(ts);
109
+ // A NUL byte can appear in neither a context nor a sourceRef, so the
110
+ // composite key is unambiguous.
111
+ const groupKey = source ? `${context}\u0000${source}` : context;
112
+ if (!byGroup.has(groupKey)) {
113
+ byGroup.set(groupKey, { context, source, values: [] });
90
114
  }
91
115
  // Vessel-name rows are stored under the synthetic path "name" (tagged
92
116
  // kind "identity") but were received as empty-path object deltas —
93
117
  // replay them in that original shape, the only one consumers
94
118
  // (Freeboard) read names from. The kind gate keeps a data path
95
119
  // literally named "name" replaying as the plain string it is.
96
- byContext
97
- .get(context)
98
- .push(path === "name" && row.kind === "identity" && typeof value === "string"
120
+ byGroup
121
+ .get(groupKey)
122
+ .values.push(path === "name" && row.kind === "identity" && typeof value === "string"
99
123
  ? { path: "", value: { name: value } }
100
124
  : { path, value });
101
125
  }
102
126
  const deltas = [];
103
- for (const [ts, byContext] of byTimestamp) {
104
- for (const [context, values] of byContext) {
127
+ for (const [ts, byGroup] of byTimestamp) {
128
+ for (const { context, source, values } of byGroup.values()) {
105
129
  deltas.push({
106
130
  context,
107
- updates: [{ timestamp: ts, values }],
131
+ updates: [
132
+ source
133
+ ? { timestamp: ts, $source: source, values }
134
+ : { timestamp: ts, values },
135
+ ],
108
136
  });
109
137
  }
110
138
  }
@@ -140,6 +168,36 @@ async function fetchLatestNames(queryClient, startTime) {
140
168
  }
141
169
  }
142
170
  export function createHistoryProviderV1(queryClient, selfContext, debug) {
171
+ // Run a unified read, retrying without whichever optional column QuestDB
172
+ // reports missing. value_kind and source are separate migrations, so
173
+ // either — or both, on an external database ensureTables() has not
174
+ // touched — can be absent independently; each retry drops only the column
175
+ // actually complained about.
176
+ //
177
+ // `state` lets a caller keep the degraded flags across calls: a playback
178
+ // session issues one read per minute of history, and re-probing from
179
+ // scratch each time pays two rejected statements per chunk on QuestDB's
180
+ // single shared worker. The default (a fresh object per call) keeps
181
+ // one-shot reads re-probing, so a read that raced the migration recovers
182
+ // on the next request rather than staying degraded until restart.
183
+ async function execUnified(build, state = { withKind: true, withSource: true }) {
184
+ for (;;) {
185
+ try {
186
+ return await queryClient.exec(build(state.withKind, state.withSource));
187
+ }
188
+ catch (err) {
189
+ if (state.withKind && isMissingKindColumn(err)) {
190
+ state.withKind = false;
191
+ continue;
192
+ }
193
+ if (state.withSource && isMissingSourceColumn(err)) {
194
+ state.withSource = false;
195
+ continue;
196
+ }
197
+ throw err;
198
+ }
199
+ }
200
+ }
143
201
  function hasAnyData(options, callback) {
144
202
  const startTime = validateTimestamp(options.startTime.toISOString());
145
203
  // "Any data" must consider every value table: a vessel recording only
@@ -195,6 +253,11 @@ export function createHistoryProviderV1(queryClient, selfContext, debug) {
195
253
  // several reads rather than truncated (see the resume logic below).
196
254
  const CHUNK_ROW_LIMIT = 10000;
197
255
  let currentTime = new Date(startTime);
256
+ // Session-scoped degraded-column flags: probe the optional columns once,
257
+ // then remember for every chunk of this playback (see execUnified). A
258
+ // new session starts fresh, so a mid-migration race degrades one
259
+ // playback, not the provider's lifetime.
260
+ const columnState = { withKind: true, withSource: true };
198
261
  async function streamChunk() {
199
262
  if (stopped)
200
263
  return;
@@ -204,13 +267,7 @@ export function createHistoryProviderV1(queryClient, selfContext, debug) {
204
267
  try {
205
268
  const window = `ts >= '${from}' AND ts < '${to}'`;
206
269
  const order = `ORDER BY ts LIMIT ${CHUNK_ROW_LIMIT}`;
207
- const result = await queryClient
208
- .exec(unionValueRowsSQL(window, order))
209
- .catch((err) => {
210
- if (!isMissingKindColumn(err))
211
- throw err;
212
- return queryClient.exec(unionValueRowsSQL(window, order, false));
213
- });
270
+ const result = await execUnified((withKind, withSource) => unionValueRowsSQL(window, order, withKind, withSource), columnState);
214
271
  if (result.dataset.length === 0) {
215
272
  currentTime = chunkEnd;
216
273
  if (!stopped) {
@@ -325,18 +382,12 @@ export function createHistoryProviderV1(queryClient, selfContext, debug) {
325
382
  const at = `ts <= '${ts}'`;
326
383
  const byPath = ` LATEST ON ts PARTITION BY path, context`;
327
384
  const byContext = ` LATEST ON ts PARTITION BY context`;
328
- const snapshotSQL = (withKind) => `(${numBranch(at, byPath)})` +
385
+ const snapshotSQL = (withKind, withSource) => `(${numBranch(at, withSource, byPath)})` +
329
386
  ` UNION ALL ` +
330
- `(${strBranch(at, withKind, byPath)})` +
387
+ `(${strBranch(at, withKind, withSource, byPath)})` +
331
388
  ` UNION ALL ` +
332
- `(${posBranch(at, byContext)})`;
333
- queryClient
334
- .exec(snapshotSQL(true))
335
- .catch((err) => {
336
- if (!isMissingKindColumn(err))
337
- throw err;
338
- return queryClient.exec(snapshotSQL(false));
339
- })
389
+ `(${posBranch(at, withSource, byContext)})`;
390
+ execUnified(snapshotSQL)
340
391
  .then((result) => {
341
392
  const rows = queryClient.toObjects(result);
342
393
  const deltas = groupRowsIntoDeltas(rows);
@@ -1 +1 @@
1
- {"version":3,"file":"history-v1.js","sourceRoot":"","sources":["../src/history-v1.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"history-v1.js","sourceRoot":"","sources":["../src/history-v1.ts"],"names":[],"mappings":"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"}