pmtiles-swarm 0.35.1 → 0.35.2

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
@@ -7,6 +7,25 @@
7
7
  ### 🐞 Bug fixes
8
8
  - _...Add new stuff here..._
9
9
 
10
+ ## 0.35.2
11
+ ### ✨ Features and improvements
12
+
13
+ ### 🐞 Bug fixes
14
+ - **A killed sidecar is reported with the signal that killed it.** `child.on('exit')` gives a null
15
+ code when a process dies by signal and puts the name in the *second* argument, which 0.35.1 did
16
+ not read — so the one case where the code carries no information printed `exited (code null)`
17
+ and withheld the word that does. It now says `killed by SIGKILL` or `killed by SIGTERM`, and
18
+ only mentions the OOM killer for `SIGKILL`, that being the one it cannot ask for politely. The
19
+ 0.35.1 wording guessed at memory whatever had happened, which on a box with 122 GiB free sent
20
+ the reader somewhere there was nothing to find.
21
+ - **The in-process hashing fallback says what it costs.** When libtorrent cannot build a torrent,
22
+ creation falls back to hashing in the node process — correct, since a torrent matters more than
23
+ its format, but not a smaller version of the same thing: it reads the whole archive in the
24
+ process that also serves tiles and the console. For a 698 GiB archive that is a console which
25
+ has apparently locked up, with nothing in the log joining it to the sidecar that died some time
26
+ earlier. The warning now names the size, says the hash is happening here, and says that fixing
27
+ libtorrent is worth more than waiting for it.
28
+
10
29
  ## 0.35.1
11
30
  ### ✨ Features and improvements
12
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmtiles-swarm",
3
- "version": "0.35.1",
3
+ "version": "0.35.2",
4
4
  "description": "BitTorrent distribution for PMTiles map archives: create torrents, watch folders, publish and subscribe to RSS feeds, and seed through qBittorrent or an embedded client",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -247,7 +247,7 @@ export class LibtorrentEngine {
247
247
  );
248
248
  });
249
249
 
250
- child.on('exit', (code) => {
250
+ child.on('exit', (code, signal) => {
251
251
  clearTimeout(timer);
252
252
  this.#child = null;
253
253
 
@@ -270,13 +270,24 @@ export class LibtorrentEngine {
270
270
  // left nothing in the log at all. What the operator saw instead was
271
271
  // "libtorrent sidecar is not running" once a second, for ever, with no
272
272
  // line anywhere saying when it stopped or why.
273
- console.error(
274
- `[libtorrent] sidecar exited (code ${code}). No stderr above this ` +
275
- 'means it was killed rather than failing the OOM killer is the ' +
276
- 'usual reason on a node hashing or downloading a large archive.',
277
- );
278
-
279
- const error = new Error(`libtorrent sidecar exited (code ${code})`);
273
+ // The signal, not just the code. A process killed by one exits with a
274
+ // null code, so reporting the code alone said "exited (code null)"
275
+ // which names the one case where the code carries no information and
276
+ // withholds the word that does. SIGKILL is the OOM killer or someone
277
+ // with a big hammer; SIGTERM is something asking politely, which for a
278
+ // sidecar nobody meant to stop is usually the service manager taking
279
+ // the whole cgroup down.
280
+ const how = signal ? `killed by ${signal}` : `exited with code ${code}`;
281
+ const why = signal
282
+ ? signal === 'SIGKILL'
283
+ ? ' Nothing asks for SIGKILL politely: on a node hashing or ' +
284
+ 'downloading a large archive this is the OOM killer, and ' +
285
+ '`dmesg -T | grep -i oom` will say so outright.'
286
+ : ''
287
+ : ' No stderr above this means it failed without saying why.';
288
+ console.error(`[libtorrent] sidecar ${how}.${why}`);
289
+
290
+ const error = new Error(`libtorrent sidecar ${how}`);
280
291
  for (const { reject: fail } of this.#pending.values()) fail(error);
281
292
  this.#pending.clear();
282
293
 
@@ -671,7 +671,21 @@ async function buildTorrent(input, name, size, options) {
671
671
  };
672
672
  } catch (error) {
673
673
  // A torrent is more important than the format of a torrent.
674
- console.warn(`[create] ${error.message}; falling back to a v1 torrent`);
674
+ //
675
+ // Said with what it costs, though, because the fallback is not a smaller
676
+ // version of the same thing. libtorrent hashes in its own process; this
677
+ // hashes in *this* one, so an archive large enough to be worth handing
678
+ // to libtorrent is now being read end to end by the process also serving
679
+ // tiles and the console — which is how a sidecar dying mid-create turns
680
+ // into a console that has apparently locked up, with nothing in the log
681
+ // connecting the two.
682
+ const gib = size ? ` (${(size / 1024 ** 3).toFixed(1)} GiB)` : '';
683
+ console.warn(
684
+ `[create] ${error.message}; hashing${gib} in this process instead, ` +
685
+ 'which is slower, holds no hybrid v2 layers, and competes with ' +
686
+ 'everything else this node is doing. Fixing whatever stopped ' +
687
+ 'libtorrent is worth more than waiting for this.',
688
+ );
675
689
  }
676
690
  }
677
691