signalk-questdb 1.5.3 → 1.5.5
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/README.md +54 -0
- package/dist/container-env.d.ts +3 -0
- package/dist/container-env.js +51 -0
- package/dist/container-env.js.map +1 -0
- package/dist/delta-routing.d.ts +1 -1
- package/dist/delta-routing.js +9 -0
- package/dist/delta-routing.js.map +1 -1
- package/dist/history-v1.js +158 -4
- package/dist/history-v1.js.map +1 -1
- package/dist/history-v2.js +105 -2
- package/dist/history-v2.js.map +1 -1
- package/dist/host-limits.d.ts +9 -0
- package/dist/host-limits.js +58 -0
- package/dist/host-limits.js.map +1 -0
- package/dist/ilp-writer.d.ts +1 -1
- package/dist/ilp-writer.js +8 -2
- package/dist/ilp-writer.js.map +1 -1
- package/dist/index.js +99 -64
- package/dist/index.js.map +1 -1
- package/dist/path-matcher.d.ts +16 -0
- package/dist/path-matcher.js +109 -0
- package/dist/path-matcher.js.map +1 -0
- package/dist/query-client.d.ts +1 -1
- package/dist/query-client.js +25 -6
- package/dist/query-client.js.map +1 -1
- package/dist/test/container-env.test.d.ts +1 -0
- package/dist/test/container-env.test.js +75 -0
- package/dist/test/container-env.test.js.map +1 -0
- package/dist/test/delta-routing.test.js +6 -0
- package/dist/test/delta-routing.test.js.map +1 -1
- package/dist/test/history-v1.test.d.ts +1 -0
- package/dist/test/history-v1.test.js +310 -0
- package/dist/test/history-v1.test.js.map +1 -0
- package/dist/test/history-v2.test.js +282 -0
- package/dist/test/history-v2.test.js.map +1 -1
- package/dist/test/host-limits.test.d.ts +1 -0
- package/dist/test/host-limits.test.js +71 -0
- package/dist/test/host-limits.test.js.map +1 -0
- package/dist/test/ilp-writer.test.js +24 -0
- package/dist/test/ilp-writer.test.js.map +1 -1
- package/dist/test/path-matcher.test.d.ts +1 -0
- package/dist/test/path-matcher.test.js +170 -0
- package/dist/test/path-matcher.test.js.map +1 -0
- package/dist/test/query-client.test.js +88 -0
- package/dist/test/query-client.test.js.map +1 -1
- package/dist/test/wal-monitor.test.js +77 -0
- package/dist/test/wal-monitor.test.js.map +1 -1
- package/dist/wal-monitor.d.ts +1 -0
- package/dist/wal-monitor.js +40 -0
- package/dist/wal-monitor.js.map +1 -1
- package/package.json +2 -2
- package/public/540.js +1 -1
- package/public/805.js +1 -1
- package/public/main.js +1 -1
- package/public/remoteEntry.js +1 -1
package/README.md
CHANGED
|
@@ -158,6 +158,31 @@ whether Signal K runs on bare metal or is itself containerized:
|
|
|
158
158
|
In **external mode** (`Managed container` off) the plugin connects to the
|
|
159
159
|
QuestDB you point it at via `QuestDB host` + the HTTP/ILP ports.
|
|
160
160
|
|
|
161
|
+
## Durability on power loss
|
|
162
|
+
|
|
163
|
+
The managed container runs QuestDB with `cairo.commit.mode=sync`.
|
|
164
|
+
|
|
165
|
+
QuestDB's default is `nosync`: nothing on the ingest path is ever fsynced, and
|
|
166
|
+
durability is left to the OS page cache. On a power cut an arbitrary subset of
|
|
167
|
+
recent writes survives — including the case where a commit record reaches disk
|
|
168
|
+
while the row data it describes does not. QuestDB then fails while _opening_
|
|
169
|
+
that table's partition, which suspends the table permanently: neither a
|
|
170
|
+
lossless `RESUME WAL` nor a bounded `RESUME WAL FROM TXN` skip can get past it,
|
|
171
|
+
because the failure happens before any transaction is read. Repair means
|
|
172
|
+
hand-patching the commit record.
|
|
173
|
+
|
|
174
|
+
With `sync`, partition columns are fsynced before the commit record is written
|
|
175
|
+
and WAL segments are fsynced on commit, so the stored state can never claim
|
|
176
|
+
data that isn't durable. The cost is a few fsyncs per commit interval — writes
|
|
177
|
+
are already batched (see `ilpFlushIntervalMs`), so at boat data rates it is
|
|
178
|
+
negligible against losing a table.
|
|
179
|
+
|
|
180
|
+
**Running an external QuestDB?** Set this yourself in `server.conf`:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
cairo.commit.mode=sync
|
|
184
|
+
```
|
|
185
|
+
|
|
161
186
|
## QuestDB Web Console
|
|
162
187
|
|
|
163
188
|
QuestDB ships a web console (SQL editor + import UI) on its HTTP port. See the
|
|
@@ -265,6 +290,35 @@ podman events --since 2h --stream=false --filter container=sk-signalk-questdb \
|
|
|
265
290
|
--filter event=oom --filter event=died
|
|
266
291
|
```
|
|
267
292
|
|
|
293
|
+
### History queries slow or timing out / "out-of-memory" errors with free RAM
|
|
294
|
+
|
|
295
|
+
QuestDB memory-maps every partition column file and every pending WAL segment
|
|
296
|
+
it touches. The Linux kernel caps how many memory mappings one process may
|
|
297
|
+
hold (`vm.max_map_count`), and the stock value on Debian, Ubuntu ≤ 22.04, and
|
|
298
|
+
RHEL (65530) is far below what QuestDB recommends (1048576). A fresh database
|
|
299
|
+
fits easily; months of daily partitions across the three tables — plus a
|
|
300
|
+
segment backlog if a table's WAL is suspended — can exhaust the limit. When
|
|
301
|
+
that happens `mmap` fails with out-of-memory errors (errno 12) **even though
|
|
302
|
+
plenty of RAM is free**: queries error out or crawl, and the WAL apply job can
|
|
303
|
+
suspend a table.
|
|
304
|
+
|
|
305
|
+
The QuestDB Web Console shows the same warning
|
|
306
|
+
(`vm.max_map_count limit is too low`), the plugin's config panel shows a
|
|
307
|
+
banner, and the server log gets a warning at plugin startup. Fix it in a
|
|
308
|
+
shell **on the host machine itself** — not inside the QuestDB container via
|
|
309
|
+
`podman exec`: the limit is kernel-global, a container cannot change it, and
|
|
310
|
+
the QuestDB image has neither `sudo` nor `/etc/sysctl.d`. Being kernel-global
|
|
311
|
+
also means this works no matter how Signal K itself is deployed:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
echo 'vm.max_map_count=1048576' | sudo tee /etc/sysctl.d/99-questdb.conf
|
|
315
|
+
sudo sysctl --system
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
This takes effect immediately — no container or host restart needed. See
|
|
319
|
+
[QuestDB capacity planning](https://questdb.com/docs/getting-started/capacity-planning/#max-virtual-memory-areas-limit)
|
|
320
|
+
for background.
|
|
321
|
+
|
|
268
322
|
## History API Provider
|
|
269
323
|
|
|
270
324
|
QuestDB automatically registers as the **default** Signal K v2 History API provider. Any app or Grafana plugin that queries `/signalk/v2/api/history/` uses QuestDB.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The QuestDB container's environment, in ONE place.
|
|
3
|
+
//
|
|
4
|
+
// There are two call sites that create the container — plugin start and
|
|
5
|
+
// /api/update/apply — and they used to build this literal independently. They
|
|
6
|
+
// had already drifted: the update path silently dropped the low-power worker
|
|
7
|
+
// tuning, so an in-place version update quietly moved a Pi onto QuestDB's
|
|
8
|
+
// multi-worker defaults. Anything a future option adds here now reaches both
|
|
9
|
+
// paths by construction.
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.QUESTDB_COMMIT_MODE = void 0;
|
|
12
|
+
exports.buildContainerEnv = buildContainerEnv;
|
|
13
|
+
// QuestDB's ingest path does not fsync anything under its default
|
|
14
|
+
// `cairo.commit.mode=nosync`: durability is left to the OS page cache, and a
|
|
15
|
+
// power cut can land the `_txn` commit record while the partition data it
|
|
16
|
+
// describes is still dirty. The table then claims more rows than exist on
|
|
17
|
+
// disk, and TableWriter asserts while OPENING the partition — a state no
|
|
18
|
+
// RESUME WAL variant can repair (both remedies run after the open), so it
|
|
19
|
+
// costs the whole table. `sync` makes TableWriter.commit00() fsync partition
|
|
20
|
+
// columns BEFORE writing the commit record, and makes WalWriter fsync each
|
|
21
|
+
// segment on commit, so the on-disk state can never claim data it doesn't
|
|
22
|
+
// have.
|
|
23
|
+
//
|
|
24
|
+
// Boats lose power; that is the deployment, not an edge case. The cost is a
|
|
25
|
+
// handful of fsyncs per commit interval (ILP batches at `ilpFlushIntervalMs`,
|
|
26
|
+
// 5s by default), which at boat data rates is noise against losing a table.
|
|
27
|
+
exports.QUESTDB_COMMIT_MODE = "sync";
|
|
28
|
+
function buildContainerEnv(config) {
|
|
29
|
+
return {
|
|
30
|
+
QDB_TELEMETRY_ENABLED: "false",
|
|
31
|
+
QDB_HTTP_ENABLED: "true",
|
|
32
|
+
QDB_LINE_TCP_ENABLED: "true",
|
|
33
|
+
QDB_CAIRO_COMMIT_MODE: exports.QUESTDB_COMMIT_MODE,
|
|
34
|
+
// Reduce CPU usage on low-power devices (Pi, Cerbo)
|
|
35
|
+
QDB_CAIRO_WAL_APPLY_WORKER_COUNT: "1",
|
|
36
|
+
QDB_SHARED_WORKER_COUNT: "1",
|
|
37
|
+
QDB_LINE_TCP_WRITER_WORKER_COUNT: "1",
|
|
38
|
+
QDB_CAIRO_O3_COLUMN_MEMORY_SIZE: "262144",
|
|
39
|
+
...(config.compression && config.compression !== "none"
|
|
40
|
+
? {
|
|
41
|
+
QDB_CAIRO_WAL_SEGMENT_COMPRESSION_CODEC: config.compression === "zstd" ? "ZSTD" : "LZ4",
|
|
42
|
+
...(config.compression === "zstd" && config.compressionLevel
|
|
43
|
+
? {
|
|
44
|
+
QDB_CAIRO_WAL_SEGMENT_COMPRESSION_LEVEL: String(config.compressionLevel),
|
|
45
|
+
}
|
|
46
|
+
: {}),
|
|
47
|
+
}
|
|
48
|
+
: {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=container-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container-env.js","sourceRoot":"","sources":["../src/container-env.ts"],"names":[],"mappings":";AAAA,qDAAqD;AACrD,EAAE;AACF,wEAAwE;AACxE,8EAA8E;AAC9E,6EAA6E;AAC7E,0EAA0E;AAC1E,6EAA6E;AAC7E,yBAAyB;;;AAoBzB,8CA2BC;AA3CD,kEAAkE;AAClE,6EAA6E;AAC7E,0EAA0E;AAC1E,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,6EAA6E;AAC7E,2EAA2E;AAC3E,0EAA0E;AAC1E,QAAQ;AACR,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,4EAA4E;AAC/D,QAAA,mBAAmB,GAAG,MAAM,CAAC;AAE1C,SAAgB,iBAAiB,CAC/B,MAAuB;IAEvB,OAAO;QACL,qBAAqB,EAAE,OAAO;QAC9B,gBAAgB,EAAE,MAAM;QACxB,oBAAoB,EAAE,MAAM;QAC5B,qBAAqB,EAAE,2BAAmB;QAC1C,oDAAoD;QACpD,gCAAgC,EAAE,GAAG;QACrC,uBAAuB,EAAE,GAAG;QAC5B,gCAAgC,EAAE,GAAG;QACrC,+BAA+B,EAAE,QAAQ;QACzC,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,KAAK,MAAM;YACrD,CAAC,CAAC;gBACE,uCAAuC,EACrC,MAAM,CAAC,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;gBAChD,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM,IAAI,MAAM,CAAC,gBAAgB;oBAC1D,CAAC,CAAC;wBACE,uCAAuC,EAAE,MAAM,CAC7C,MAAM,CAAC,gBAAgB,CACxB;qBACF;oBACH,CAAC,CAAC,EAAE,CAAC;aACR;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC"}
|
package/dist/delta-routing.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type DeltaRoute = "number" | "string" | "position" | null;
|
|
1
|
+
export type DeltaRoute = "number" | "string" | "boolean" | "position" | null;
|
|
2
2
|
export declare function routeDeltaValue(path: string, value: unknown): DeltaRoute;
|
package/dist/delta-routing.js
CHANGED
|
@@ -6,6 +6,15 @@ function routeDeltaValue(path, value) {
|
|
|
6
6
|
return "number";
|
|
7
7
|
if (typeof value === "string")
|
|
8
8
|
return "string";
|
|
9
|
+
// Booleans are everywhere in Signal K — switch and relay states, pump and
|
|
10
|
+
// valve states, autopilot flags — and used to fall through to null, so a
|
|
11
|
+
// whole class of history was dropped without a trace. They go to
|
|
12
|
+
// signalk_str as "true"/"false" rather than 0/1 in the numeric table: the
|
|
13
|
+
// string round-trips unambiguously (a 1.0 double cannot be told apart from
|
|
14
|
+
// a real numeric channel), and it needs no schema change, so dedup keys,
|
|
15
|
+
// retention and the history API all apply unchanged.
|
|
16
|
+
if (typeof value === "boolean")
|
|
17
|
+
return "boolean";
|
|
9
18
|
if (path === "navigation.position" &&
|
|
10
19
|
value !== null &&
|
|
11
20
|
typeof value === "object" &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delta-routing.js","sourceRoot":"","sources":["../src/delta-routing.ts"],"names":[],"mappings":";;AAUA,
|
|
1
|
+
{"version":3,"file":"delta-routing.js","sourceRoot":"","sources":["../src/delta-routing.ts"],"names":[],"mappings":";;AAUA,0CAsBC;AAtBD,SAAgB,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"}
|
package/dist/history-v1.js
CHANGED
|
@@ -2,13 +2,88 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createHistoryProviderV1 = createHistoryProviderV1;
|
|
4
4
|
const query_client_1 = require("./query-client");
|
|
5
|
+
// v1 replays raw deltas rather than aggregating, so all three value tables can
|
|
6
|
+
// be read in one pass and interleaved by timestamp. Every branch below emits
|
|
7
|
+
// the same unified shape — ts, path, context, valuetext, kind — which
|
|
8
|
+
// decodeValue turns back into the real delta value; the CASTs exist to keep
|
|
9
|
+
// the union's column types compatible.
|
|
10
|
+
//
|
|
11
|
+
// One builder per table, shared by BOTH query shapes (windowed streaming and
|
|
12
|
+
// the LATEST ON snapshot). `tail` carries what the caller appends inside the
|
|
13
|
+
// branch — the snapshot's LATEST ON clause. Keeping every branch here is the
|
|
14
|
+
// point: the snapshot query used to re-implement these by hand and drifted,
|
|
15
|
+
// silently replaying booleans as text on that path only.
|
|
16
|
+
function numBranch(where, tail = "") {
|
|
17
|
+
return (`SELECT ts, path, context, CAST(value AS STRING) valuetext, ` +
|
|
18
|
+
`'number' kind FROM signalk WHERE ${where}${tail}`);
|
|
19
|
+
}
|
|
20
|
+
// `withKind: false` degrades to the pre-migration shape. ensureTables() adds
|
|
21
|
+
// value_kind at startup, but a read racing an unmigrated table (or an
|
|
22
|
+
// external QuestDB the plugin does not own) would otherwise fail the WHOLE
|
|
23
|
+
// union with "Invalid column: value_kind" — turning a missing type tag into
|
|
24
|
+
// no history at all. The NULL is cast so the union's column type is stated
|
|
25
|
+
// rather than inferred.
|
|
26
|
+
function strBranch(where, withKind, tail = "") {
|
|
27
|
+
const kind = withKind ? `CAST(value_kind AS STRING)` : `CAST(NULL AS STRING)`;
|
|
28
|
+
return (`SELECT ts, path, context, value_str valuetext, ${kind} kind ` +
|
|
29
|
+
`FROM signalk_str WHERE ${where}${tail}`);
|
|
30
|
+
}
|
|
31
|
+
// The track table has no path column, so the path is supplied as a literal.
|
|
32
|
+
function posBranch(where, tail = "") {
|
|
33
|
+
return (`SELECT ts, 'navigation.position' path, context, ` +
|
|
34
|
+
`concat(CAST(lat AS STRING), ',', CAST(lon AS STRING)) valuetext, ` +
|
|
35
|
+
`'position' kind FROM signalk_position WHERE ${where}${tail}`);
|
|
36
|
+
}
|
|
37
|
+
function unionValueRowsSQL(where, orderAndLimit, withKind = true) {
|
|
38
|
+
return (`${numBranch(where)} UNION ALL ` +
|
|
39
|
+
`${strBranch(where, withKind)} UNION ALL ` +
|
|
40
|
+
`${posBranch(where)} ${orderAndLimit}`);
|
|
41
|
+
}
|
|
42
|
+
// True for the error QuestDB returns when value_kind has not been added yet.
|
|
43
|
+
function isMissingKindColumn(err) {
|
|
44
|
+
return /Invalid column:\s*value_kind/i.test(err instanceof Error ? err.message : String(err));
|
|
45
|
+
}
|
|
46
|
+
// Turn a unified row back into the value a Signal K delta carries. Numbers
|
|
47
|
+
// must not stay strings (consumers do arithmetic on them), positions must be
|
|
48
|
+
// objects again, and a value recorded as a boolean must replay as a boolean.
|
|
49
|
+
//
|
|
50
|
+
// Only rows explicitly tagged 'boolean' are converted: the text is parsed
|
|
51
|
+
// from the stored value, never guessed. A path whose value genuinely is the
|
|
52
|
+
// word "true" carries no tag and stays a string — as do all rows written
|
|
53
|
+
// before the value_kind column existed, whose original type is not
|
|
54
|
+
// recoverable.
|
|
55
|
+
function decodeValue(row) {
|
|
56
|
+
const text = row.valuetext;
|
|
57
|
+
if (text === null || text === undefined)
|
|
58
|
+
return null;
|
|
59
|
+
switch (row.kind) {
|
|
60
|
+
case "number": {
|
|
61
|
+
const n = Number(text);
|
|
62
|
+
return Number.isFinite(n) ? n : null;
|
|
63
|
+
}
|
|
64
|
+
case "boolean":
|
|
65
|
+
return String(text) === "true";
|
|
66
|
+
case "position": {
|
|
67
|
+
const [lat, lon] = String(text).split(",");
|
|
68
|
+
const latitude = Number(lat);
|
|
69
|
+
const longitude = Number(lon);
|
|
70
|
+
return Number.isFinite(latitude) && Number.isFinite(longitude)
|
|
71
|
+
? { latitude, longitude }
|
|
72
|
+
: null;
|
|
73
|
+
}
|
|
74
|
+
default:
|
|
75
|
+
return text;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
5
78
|
function groupRowsIntoDeltas(rows) {
|
|
6
79
|
const byTimestamp = new Map();
|
|
7
80
|
for (const row of rows) {
|
|
8
81
|
const ts = row.ts;
|
|
9
82
|
const context = row.context || "self";
|
|
10
83
|
const path = row.path;
|
|
11
|
-
|
|
84
|
+
// Both call sites query the unified shape, so every row carries
|
|
85
|
+
// `valuetext` + `kind` for decodeValue to reconstruct.
|
|
86
|
+
const value = decodeValue(row);
|
|
12
87
|
if (!byTimestamp.has(ts)) {
|
|
13
88
|
byTimestamp.set(ts, new Map());
|
|
14
89
|
}
|
|
@@ -32,8 +107,17 @@ function groupRowsIntoDeltas(rows) {
|
|
|
32
107
|
function createHistoryProviderV1(queryClient, selfContext, debug) {
|
|
33
108
|
function hasAnyData(options, callback) {
|
|
34
109
|
const startTime = (0, query_client_1.validateTimestamp)(options.startTime.toISOString());
|
|
110
|
+
// "Any data" must consider every value table: a vessel recording only
|
|
111
|
+
// string/boolean channels (or only a position track) has history to play
|
|
112
|
+
// back, and answering false here disables playback entirely.
|
|
35
113
|
queryClient
|
|
36
|
-
.exec(
|
|
114
|
+
.exec(
|
|
115
|
+
// Summed via a UNION ALL subquery: QuestDB rejects adding scalar
|
|
116
|
+
// subqueries with `+` ("no matching operator").
|
|
117
|
+
`SELECT sum(c) as cnt FROM (` +
|
|
118
|
+
`SELECT count() c FROM signalk WHERE ts >= '${startTime}'` +
|
|
119
|
+
` UNION ALL SELECT count() c FROM signalk_str WHERE ts >= '${startTime}'` +
|
|
120
|
+
` UNION ALL SELECT count() c FROM signalk_position WHERE ts >= '${startTime}')`)
|
|
37
121
|
.then((result) => {
|
|
38
122
|
const count = result.dataset.length > 0 ? result.dataset[0][0] : 0;
|
|
39
123
|
callback(count > 0);
|
|
@@ -49,6 +133,9 @@ function createHistoryProviderV1(queryClient, selfContext, debug) {
|
|
|
49
133
|
const startTime = (0, query_client_1.validateTimestamp)(options.startTime.toISOString());
|
|
50
134
|
const playbackRate = Math.max(1, options.playbackRate);
|
|
51
135
|
const CHUNK_SECONDS = 60;
|
|
136
|
+
// Rows per read. A window holding more than this is drained across
|
|
137
|
+
// several reads rather than truncated (see the resume logic below).
|
|
138
|
+
const CHUNK_ROW_LIMIT = 10000;
|
|
52
139
|
let currentTime = new Date(startTime);
|
|
53
140
|
async function streamChunk() {
|
|
54
141
|
if (stopped)
|
|
@@ -57,7 +144,15 @@ function createHistoryProviderV1(queryClient, selfContext, debug) {
|
|
|
57
144
|
const chunkEnd = new Date(currentTime.getTime() + CHUNK_SECONDS * 1000);
|
|
58
145
|
const to = (0, query_client_1.validateTimestamp)(chunkEnd.toISOString());
|
|
59
146
|
try {
|
|
60
|
-
const
|
|
147
|
+
const window = `ts >= '${from}' AND ts < '${to}'`;
|
|
148
|
+
const order = `ORDER BY ts LIMIT ${CHUNK_ROW_LIMIT}`;
|
|
149
|
+
const result = await queryClient
|
|
150
|
+
.exec(unionValueRowsSQL(window, order))
|
|
151
|
+
.catch((err) => {
|
|
152
|
+
if (!isMissingKindColumn(err))
|
|
153
|
+
throw err;
|
|
154
|
+
return queryClient.exec(unionValueRowsSQL(window, order, false));
|
|
155
|
+
});
|
|
61
156
|
if (result.dataset.length === 0) {
|
|
62
157
|
currentTime = chunkEnd;
|
|
63
158
|
if (!stopped) {
|
|
@@ -76,6 +171,37 @@ function createHistoryProviderV1(queryClient, selfContext, debug) {
|
|
|
76
171
|
context: resolvedContext,
|
|
77
172
|
});
|
|
78
173
|
}
|
|
174
|
+
// A busy interval can hold more rows than one read returns — querying
|
|
175
|
+
// three tables instead of one makes that far likelier (a live install
|
|
176
|
+
// already reaches ~6k rows per 60s window). Advancing to chunkEnd
|
|
177
|
+
// after a truncated read would skip the remainder silently, so drain
|
|
178
|
+
// the window before moving on.
|
|
179
|
+
//
|
|
180
|
+
// Resume AT the last sent row's timestamp, not past it: QuestDB
|
|
181
|
+
// stamps at microsecond precision but JS Date truncates to
|
|
182
|
+
// milliseconds, and a single instrument update commonly stamps
|
|
183
|
+
// several paths within the same millisecond. Stepping past it would
|
|
184
|
+
// drop the siblings that did not fit in this page. Re-reading that
|
|
185
|
+
// millisecond can re-send rows already delivered, which is harmless
|
|
186
|
+
// on replay — losing them is not.
|
|
187
|
+
//
|
|
188
|
+
// Only when the whole page shared currentTime's millisecond (so
|
|
189
|
+
// resuming at it would repeat the identical read forever) does the
|
|
190
|
+
// cursor step forward by 1ms, trading that millisecond's tail for
|
|
191
|
+
// guaranteed progress.
|
|
192
|
+
// Guard on `rows`, not `dataset`: toObjects() returns [] when the
|
|
193
|
+
// response carries no column metadata, and indexing the last row of
|
|
194
|
+
// an empty array would throw into the catch below — turning a
|
|
195
|
+
// metadata hiccup into a permanent 1s retry loop on this window.
|
|
196
|
+
if (rows.length >= CHUNK_ROW_LIMIT) {
|
|
197
|
+
const lastTs = new Date(rows[rows.length - 1].ts).getTime();
|
|
198
|
+
const resumeAt = lastTs > currentTime.getTime() ? lastTs : currentTime.getTime() + 1;
|
|
199
|
+
currentTime = new Date(Math.min(resumeAt, chunkEnd.getTime()));
|
|
200
|
+
if (!stopped) {
|
|
201
|
+
setTimeout(streamChunk, 0);
|
|
202
|
+
}
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
79
205
|
currentTime = chunkEnd;
|
|
80
206
|
const wallDelay = (CHUNK_SECONDS * 1000) / playbackRate;
|
|
81
207
|
if (!stopped) {
|
|
@@ -97,10 +223,38 @@ function createHistoryProviderV1(queryClient, selfContext, debug) {
|
|
|
97
223
|
stopped = true;
|
|
98
224
|
};
|
|
99
225
|
}
|
|
226
|
+
// Snapshot of every path at `date`, for the v1 snapshot API.
|
|
227
|
+
//
|
|
228
|
+
// `path` is deliberately unused and must NOT become a filter. Despite the
|
|
229
|
+
// name (and the `string` in the server's provider interface), the server
|
|
230
|
+
// passes the REQUEST URL SEGMENTS — e.g. ["vessels", "<selfId>",
|
|
231
|
+
// "navigation"], or [] for the root snapshot — then feeds every returned
|
|
232
|
+
// delta to buildFullFromDeltas() and walks into the assembled tree with
|
|
233
|
+
// those segments (signalk-server src/interfaces/rest.js). Filtering the
|
|
234
|
+
// query by it would both mismatch the type and starve the snapshot the
|
|
235
|
+
// caller is building.
|
|
100
236
|
function getHistory(date, path, callback) {
|
|
101
237
|
const ts = (0, query_client_1.validateTimestamp)(date.toISOString());
|
|
238
|
+
// LATEST ON is applied PER TABLE and the results unioned, not the other
|
|
239
|
+
// way round: running it over a materialized union makes QuestDB scan
|
|
240
|
+
// instead of using each table's index, which timed out (>30s) on a
|
|
241
|
+
// multi-hundred-million-row install. Position partitions by context only
|
|
242
|
+
// — the track table has no path column.
|
|
243
|
+
const at = `ts <= '${ts}'`;
|
|
244
|
+
const byPath = ` LATEST ON ts PARTITION BY path, context`;
|
|
245
|
+
const byContext = ` LATEST ON ts PARTITION BY context`;
|
|
246
|
+
const snapshotSQL = (withKind) => `(${numBranch(at, byPath)})` +
|
|
247
|
+
` UNION ALL ` +
|
|
248
|
+
`(${strBranch(at, withKind, byPath)})` +
|
|
249
|
+
` UNION ALL ` +
|
|
250
|
+
`(${posBranch(at, byContext)})`;
|
|
102
251
|
queryClient
|
|
103
|
-
.exec(
|
|
252
|
+
.exec(snapshotSQL(true))
|
|
253
|
+
.catch((err) => {
|
|
254
|
+
if (!isMissingKindColumn(err))
|
|
255
|
+
throw err;
|
|
256
|
+
return queryClient.exec(snapshotSQL(false));
|
|
257
|
+
})
|
|
104
258
|
.then((result) => {
|
|
105
259
|
const rows = queryClient.toObjects(result);
|
|
106
260
|
const deltas = groupRowsIntoDeltas(rows);
|
package/dist/history-v1.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history-v1.js","sourceRoot":"","sources":["../src/history-v1.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"history-v1.js","sourceRoot":"","sources":["../src/history-v1.ts"],"names":[],"mappings":"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"}
|
package/dist/history-v2.js
CHANGED
|
@@ -82,9 +82,80 @@ function normalizeContext(context, selfContext) {
|
|
|
82
82
|
}
|
|
83
83
|
return context;
|
|
84
84
|
}
|
|
85
|
+
// Upper bound on SAMPLE BY buckets a single request may generate. The
|
|
86
|
+
// SAMPLE BY queries use FILL(NULL), which fabricates a row for EVERY bucket
|
|
87
|
+
// in the range whether data exists or not — a caller asking for weeks at 1s
|
|
88
|
+
// resolution would stream millions of rows through QuestDB, Node's JSON
|
|
89
|
+
// parser, and the HTTP response, wedging Pi-class servers for minutes. The
|
|
90
|
+
// well-behaved clients budget ~2000 points per request; a million covers any
|
|
91
|
+
// sane chart while keeping the worst case bounded.
|
|
92
|
+
const MAX_SAMPLE_BUCKETS = 1_000_000;
|
|
93
|
+
// Effective SAMPLE BY period: QuestDB rejects `SAMPLE BY 0s`, so fractional
|
|
94
|
+
// resolutions (e.g. 0.5) must clamp up to 1s instead of flooring to zero.
|
|
95
|
+
function effectiveResolution(resolution) {
|
|
96
|
+
return Math.max(1, Math.floor(resolution));
|
|
97
|
+
}
|
|
85
98
|
function createHistoryProviderV2(queryClient, selfContext) {
|
|
99
|
+
// Read a path's rows from signalk_str. Numeric aggregates do not apply to
|
|
100
|
+
// text, so a downsampled request takes one representative value per bucket
|
|
101
|
+
// (last = the state in force at the bucket's end, which is what a state
|
|
102
|
+
// channel means) instead of averaging. Values are returned verbatim:
|
|
103
|
+
// booleans were stored as "true"/"false", so a consumer can tell them apart
|
|
104
|
+
// from real numbers, and Grafana value mappings work directly.
|
|
105
|
+
async function readStringRows(where, resolution) {
|
|
106
|
+
// `value_kind` marks rows that were recorded as booleans, so v2 replays
|
|
107
|
+
// them as real booleans exactly like v1 — otherwise the same path would
|
|
108
|
+
// read `true` through one API and `"true"` through the other. Untagged
|
|
109
|
+
// rows (plain text, and everything written before the column existed)
|
|
110
|
+
// stay strings; the text is never guessed at.
|
|
111
|
+
const sql = (withKind) => {
|
|
112
|
+
const kind = withKind ? "value_kind" : "NULL";
|
|
113
|
+
return resolution && resolution > 0
|
|
114
|
+
? `SELECT ts, last(value_str) as value_str, last(${kind}) as value_kind FROM signalk_str WHERE ${where} SAMPLE BY ${effectiveResolution(resolution)}s FILL(NULL) ORDER BY ts`
|
|
115
|
+
: `SELECT ts, value_str, ${kind} as value_kind FROM signalk_str WHERE ${where} ORDER BY ts LIMIT 10000`;
|
|
116
|
+
};
|
|
117
|
+
// A read racing ensureTables()'s migration — or an external QuestDB the
|
|
118
|
+
// plugin does not own — must degrade to text, not fail the request.
|
|
119
|
+
const result = await queryClient.exec(sql(true)).catch((err) => {
|
|
120
|
+
if (!/Invalid column:\s*value_kind/i.test(String(err)))
|
|
121
|
+
throw err;
|
|
122
|
+
return queryClient.exec(sql(false));
|
|
123
|
+
});
|
|
124
|
+
return result.dataset.map((row) => [
|
|
125
|
+
row[0],
|
|
126
|
+
row[2] === "boolean" ? row[1] === "true" : row[1],
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
86
129
|
async function getValues(query) {
|
|
87
130
|
const range = (0, time_range_1.resolveTimeRange)(query);
|
|
131
|
+
// Only specs that actually run a SAMPLE BY query fabricate buckets:
|
|
132
|
+
// client-side aggregates (sma/ema/middle_index) read raw rows under a
|
|
133
|
+
// LIMIT and must not trip the cap. Each qualifying spec issues its own
|
|
134
|
+
// SAMPLE BY, so the fabricated total scales with their count.
|
|
135
|
+
//
|
|
136
|
+
// A non-numeric path costs TWO such queries: the numeric one comes back
|
|
137
|
+
// empty and the string-table fallback repeats it against signalk_str.
|
|
138
|
+
// Which paths those are is only known after querying, so the budget
|
|
139
|
+
// assumes the worst case — every sampled spec falling back — rather than
|
|
140
|
+
// letting a request built entirely of boolean/string paths quietly run at
|
|
141
|
+
// twice the ceiling this cap exists to enforce on Pi-class hosts.
|
|
142
|
+
const sampledSpecs = query.pathSpecs.filter((spec) => spec.path === "navigation.position" ||
|
|
143
|
+
!needsClientSideAggregation(spec.aggregate)).length;
|
|
144
|
+
// navigation.position is served by its own table and never falls back.
|
|
145
|
+
const fallbackCapableSpecs = query.pathSpecs.filter((spec) => spec.path !== "navigation.position" &&
|
|
146
|
+
!needsClientSideAggregation(spec.aggregate)).length;
|
|
147
|
+
if (sampledSpecs > 0 && query.resolution && query.resolution > 0) {
|
|
148
|
+
const rangeSec = (Date.parse(range.to) - Date.parse(range.from)) / 1000;
|
|
149
|
+
const bucketsPerSeries = Math.ceil(rangeSec / effectiveResolution(query.resolution));
|
|
150
|
+
const worstCaseQueries = sampledSpecs + fallbackCapableSpecs;
|
|
151
|
+
const buckets = bucketsPerSeries * worstCaseQueries;
|
|
152
|
+
if (buckets > MAX_SAMPLE_BUCKETS) {
|
|
153
|
+
throw new Error(`resolution ${query.resolution}s over this range produces up to ` +
|
|
154
|
+
`${buckets} sample buckets across ${sampledSpecs} paths ` +
|
|
155
|
+
`(max ${MAX_SAMPLE_BUCKETS}) — use a coarser resolution or ` +
|
|
156
|
+
`a shorter range`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
88
159
|
const requestedContext = query.context ?? "vessels.self";
|
|
89
160
|
const storedContext = normalizeContext(requestedContext, selfContext);
|
|
90
161
|
const safeContext = (0, query_client_1.validateIdentifier)(storedContext);
|
|
@@ -104,7 +175,7 @@ function createHistoryProviderV2(queryClient, selfContext) {
|
|
|
104
175
|
const posAgg = spec.aggregate === "last" ? "last" : "first";
|
|
105
176
|
let sql;
|
|
106
177
|
if (query.resolution && query.resolution > 0) {
|
|
107
|
-
sql = `SELECT ts, ${posAgg}(lat) as lat, ${posAgg}(lon) as lon FROM ${table} WHERE ${where} SAMPLE BY ${
|
|
178
|
+
sql = `SELECT ts, ${posAgg}(lat) as lat, ${posAgg}(lon) as lon FROM ${table} WHERE ${where} SAMPLE BY ${effectiveResolution(query.resolution)}s FILL(NULL) ORDER BY ts`;
|
|
108
179
|
}
|
|
109
180
|
else {
|
|
110
181
|
sql = `SELECT ts, lat, lon FROM ${table} WHERE ${where} ORDER BY ts LIMIT 10000`;
|
|
@@ -148,7 +219,7 @@ function createHistoryProviderV2(queryClient, selfContext) {
|
|
|
148
219
|
const aggExpr = aggregateToSql(spec.aggregate);
|
|
149
220
|
let sql;
|
|
150
221
|
if (query.resolution && query.resolution > 0) {
|
|
151
|
-
sql = `SELECT ts, ${aggExpr} as agg_value FROM ${table} WHERE ${where} SAMPLE BY ${
|
|
222
|
+
sql = `SELECT ts, ${aggExpr} as agg_value FROM ${table} WHERE ${where} SAMPLE BY ${effectiveResolution(query.resolution)}s FILL(NULL) ORDER BY ts`;
|
|
152
223
|
}
|
|
153
224
|
else {
|
|
154
225
|
sql = `SELECT ts, value FROM ${table} WHERE ${where} ORDER BY ts LIMIT 10000`;
|
|
@@ -158,6 +229,26 @@ function createHistoryProviderV2(queryClient, selfContext) {
|
|
|
158
229
|
row[0],
|
|
159
230
|
row[1],
|
|
160
231
|
]);
|
|
232
|
+
// Non-numeric paths (strings, and booleans stored as "true"/"false")
|
|
233
|
+
// live in signalk_str, which this query never touches — they used to
|
|
234
|
+
// come back empty even though getPaths lists them. Fall back to the
|
|
235
|
+
// string table when the numeric one held nothing for this path.
|
|
236
|
+
// Emptiness is judged on VALUES, not row count: a SAMPLE BY with
|
|
237
|
+
// FILL(NULL) fabricates a row per bucket, so an all-null result is
|
|
238
|
+
// still "no numeric data here".
|
|
239
|
+
if (!rows.some(([, value]) => value !== null)) {
|
|
240
|
+
// Report the aggregate that was actually applied. Downsampled string
|
|
241
|
+
// rows always use last() — averaging text is meaningless — so leaving
|
|
242
|
+
// the caller's requested method in the response would label the
|
|
243
|
+
// series with an aggregation that never ran.
|
|
244
|
+
if (query.resolution && query.resolution > 0) {
|
|
245
|
+
const reported = valuesList[valuesList.length - 1];
|
|
246
|
+
if (reported.path === spec.path)
|
|
247
|
+
reported.method = "last";
|
|
248
|
+
}
|
|
249
|
+
columnData.set(spec.path, await readStringRows(where, query.resolution));
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
161
252
|
columnData.set(spec.path, rows);
|
|
162
253
|
}
|
|
163
254
|
const allTimestamps = new Set();
|
|
@@ -194,18 +285,30 @@ function createHistoryProviderV2(queryClient, selfContext) {
|
|
|
194
285
|
async function getPaths(query) {
|
|
195
286
|
const range = (0, time_range_1.resolveTimeRange)(query);
|
|
196
287
|
const where = buildRangeWhere(range);
|
|
288
|
+
// signalk_position has no `path` column — the whole table IS
|
|
289
|
+
// navigation.position — so it contributes that name as a literal. Without
|
|
290
|
+
// this branch getValues happily serves the track while getPaths never
|
|
291
|
+
// advertised it, so a client enumerating paths could not discover the one
|
|
292
|
+
// series it most likely wants.
|
|
197
293
|
const result = await queryClient.exec(`SELECT DISTINCT path FROM signalk WHERE ${where}
|
|
198
294
|
UNION
|
|
199
295
|
SELECT DISTINCT path FROM signalk_str WHERE ${where}
|
|
296
|
+
UNION
|
|
297
|
+
SELECT DISTINCT 'navigation.position' path FROM signalk_position WHERE ${where}
|
|
200
298
|
ORDER BY path`);
|
|
201
299
|
return result.dataset.map((row) => row[0]);
|
|
202
300
|
}
|
|
203
301
|
async function getContexts(query) {
|
|
204
302
|
const range = (0, time_range_1.resolveTimeRange)(query);
|
|
205
303
|
const where = buildRangeWhere(range);
|
|
304
|
+
// Include the track table: a vessel can be position-only (an AIS target
|
|
305
|
+
// whose other paths are filtered out, or a receiver sending nothing but
|
|
306
|
+
// fixes), and omitting it hides that context entirely.
|
|
206
307
|
const result = await queryClient.exec(`SELECT DISTINCT context FROM signalk WHERE ${where}
|
|
207
308
|
UNION
|
|
208
309
|
SELECT DISTINCT context FROM signalk_str WHERE ${where}
|
|
310
|
+
UNION
|
|
311
|
+
SELECT DISTINCT context FROM signalk_position WHERE ${where}
|
|
209
312
|
ORDER BY context`);
|
|
210
313
|
// Translate stored "self" back to the spec-canonical "vessels.self"
|
|
211
314
|
return result.dataset.map((row) => {
|
package/dist/history-v2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history-v2.js","sourceRoot":"","sources":["../src/history-v2.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"history-v2.js","sourceRoot":"","sources":["../src/history-v2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const RECOMMENDED_MAX_MAP_COUNT = 1048576;
|
|
2
|
+
export interface MaxMapCountStatus {
|
|
3
|
+
current: number;
|
|
4
|
+
recommended: number;
|
|
5
|
+
tooLow: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseMaxMapCount(content: string): number | null;
|
|
8
|
+
export declare function evaluateMaxMapCount(current: number): MaxMapCountStatus;
|
|
9
|
+
export declare function readMaxMapCount(path?: string): Promise<MaxMapCountStatus | null>;
|