sailkick-boat 0.18.0 → 0.18.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/README.md CHANGED
@@ -236,6 +236,13 @@ a source archive that is still being written — a `signalk-to-influxdb-v2` buck
236
236
  recording — makes the first windows re-upload today's data. The timestamps are correct,
237
237
  but it is data the cloud already has, and a lot of wasted uplink.
238
238
 
239
+ **Field types come from the source, not from guessing.** Queries ask InfluxDB for the
240
+ `#datatype` annotation explicitly. Without it the response is unannotated and types have
241
+ to be inferred from the text — which fails hard on a string field whose values sometimes
242
+ look numeric (`"8"` emitted bare as a float, `"1.2.3.4"` quoted as a string), producing
243
+ `422 field type conflict` and aborting the run. Integers also keep their type instead of
244
+ silently becoming floats.
245
+
239
246
  **Dense archives are subdivided.** A window is read whole and converted in memory, and a
240
247
  busy boat can produce millions of points an hour (54M/day was measured on a real boat —
241
248
  about 400 MB of CSV per hour). When a window holds more than `maxRowsPerChunk` points it
@@ -79,14 +79,26 @@ function createBackfill (app, options) {
79
79
  }
80
80
 
81
81
  // --- InfluxDB reads -----------------------------------------------------------
82
+ // Always ask for the #datatype annotation. A raw-Flux body (Content-Type
83
+ // application/vnd.flux) cannot carry a dialect, and InfluxDB then returns UNANNOTATED
84
+ // CSV — so field types have to be guessed from the text, and guessing is wrong in a
85
+ // way that breaks the write outright.
86
+ //
87
+ // The case that bit: a STRING field whose values sometimes look numeric. "8" is
88
+ // emitted bare (a float) while "1.2.3.4" is quoted (a string), so one batch declares
89
+ // two types for one field and InfluxDB rejects the lot with
90
+ // 422 field type conflict: input field "value" on measurement "network..."
91
+ // With the annotation the source declares `string` and every value is quoted
92
+ // consistently. Integers keep their `i` suffix too, instead of silently becoming
93
+ // floats.
82
94
  async function flux (conn, body) {
83
95
  const url = `${conn.url.replace(/\/+$/, '')}/api/v2/query?org=${encodeURIComponent(conn.org)}`
84
96
  let resp
85
97
  try {
86
98
  resp = await fetch(url, {
87
99
  method: 'POST',
88
- headers: { Authorization: `Token ${conn.token}`, 'Content-Type': 'application/vnd.flux', Accept: 'application/csv' },
89
- body,
100
+ headers: { Authorization: `Token ${conn.token}`, 'Content-Type': 'application/json', Accept: 'application/csv' },
101
+ body: JSON.stringify({ type: 'flux', query: body, dialect: { header: true, annotations: ['datatype'] } }),
90
102
  signal: AbortSignal.timeout(cfg.queryTimeoutMs)
91
103
  })
92
104
  } catch (e) { return { ok: false, message: e.message } }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sailkick-boat",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "EARLY ALPHA — cloud telemetry + offline maps for sailkick boats (www.sailkick.io; register on the web, paste the write token). Gapless boat→cloud telemetry sync to InfluxDB, and a local proxy that keeps the sailkick app and its charts/maps working fully offline on board.",
5
5
  "main": "index.js",
6
6
  "scripts": {