pmtiles-swarm 0.14.1 → 0.14.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 +19 -0
- package/package.json +1 -1
- package/src/publisher.js +58 -21
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,25 @@
|
|
|
7
7
|
### 🐞 Bug fixes
|
|
8
8
|
- _...Add new stuff here..._
|
|
9
9
|
|
|
10
|
+
## 0.14.2
|
|
11
|
+
### 🐞 Bug fixes
|
|
12
|
+
- **Waiting for the DHT's `ready` event was not enough.** It fires when the bootstrap lookup
|
|
13
|
+
*finishes*, whether or not that lookup found anything — so a node with no working UDP path
|
|
14
|
+
reports itself ready and then fails every put with "No nodes to query", and the warning added in
|
|
15
|
+
0.14.1 never fired because nothing had gone wrong by its measure.
|
|
16
|
+
|
|
17
|
+
It now waits for the routing table to have something in it, and says how empty it is when it
|
|
18
|
+
gives up:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
[mutable] DHT ready with 42 nodes
|
|
22
|
+
[mutable] the DHT found no peers in 60s. Publishing will fail until it does — check that
|
|
23
|
+
outbound UDP is not blocked, and that the bootstrap hosts resolve
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Per-category failures carry the count too, because "No nodes to query" with an empty table is a
|
|
27
|
+
network problem and the same message with a populated one is not.
|
|
28
|
+
|
|
10
29
|
## 0.14.1
|
|
11
30
|
### 🐞 Bug fixes
|
|
12
31
|
- **The publisher waited a fixed fifteen seconds for the DHT and then published into an empty
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmtiles-swarm",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.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",
|
package/src/publisher.js
CHANGED
|
@@ -138,8 +138,14 @@ export class MutablePublisher {
|
|
|
138
138
|
);
|
|
139
139
|
}
|
|
140
140
|
} catch (error) {
|
|
141
|
-
// One category failing must not stop the rest.
|
|
142
|
-
|
|
141
|
+
// One category failing must not stop the rest. The node count goes in
|
|
142
|
+
// the line because "No nodes to query" with an empty table is a
|
|
143
|
+
// network problem and the same message with a full one is not.
|
|
144
|
+
const nodes = this.#nodeCount();
|
|
145
|
+
this.#log(
|
|
146
|
+
`[mutable] ${category} failed: ${error.message}` +
|
|
147
|
+
(nodes === null ? '' : ` (${nodes} DHT nodes known)`),
|
|
148
|
+
);
|
|
143
149
|
}
|
|
144
150
|
}
|
|
145
151
|
if (done.length === 0 && this.#current().size > 0) {
|
|
@@ -200,37 +206,68 @@ export class MutablePublisher {
|
|
|
200
206
|
* @returns {Promise<void>} - Resolves once the first attempt is done.
|
|
201
207
|
*/
|
|
202
208
|
async #firstPublish(readyMs) {
|
|
203
|
-
const
|
|
209
|
+
const nodes = await this.#whenDhtReady(readyMs);
|
|
204
210
|
if (this.#stopped) return;
|
|
205
|
-
if (
|
|
206
|
-
//
|
|
207
|
-
//
|
|
211
|
+
if (nodes === 0) {
|
|
212
|
+
// Named rather than left to be inferred. A routing table that is still
|
|
213
|
+
// empty after a minute means the bootstrap queries are not being
|
|
214
|
+
// answered, and every "No nodes to query" after this is that same fact
|
|
215
|
+
// reported once per category.
|
|
208
216
|
this.#log(
|
|
209
|
-
`[mutable] the DHT
|
|
210
|
-
'
|
|
217
|
+
`[mutable] the DHT found no peers in ${Math.round(readyMs / 1000)}s. Publishing ` +
|
|
218
|
+
'will fail until it does — check that outbound UDP is not blocked, and that ' +
|
|
219
|
+
'the bootstrap hosts resolve',
|
|
211
220
|
);
|
|
221
|
+
} else if (nodes) {
|
|
222
|
+
this.#log(`[mutable] DHT ready with ${nodes} nodes`);
|
|
212
223
|
}
|
|
213
224
|
await this.publishAll({ force: true });
|
|
214
225
|
}
|
|
215
226
|
|
|
216
227
|
/**
|
|
217
|
-
*
|
|
228
|
+
* Waits for the DHT to have somewhere to send a query.
|
|
229
|
+
*
|
|
230
|
+
* `ready` alone is not enough: it fires when the bootstrap lookup finishes,
|
|
231
|
+
* whether or not that lookup found anything, so a node with no UDP path
|
|
232
|
+
* reports itself ready and then fails every put with "No nodes to query".
|
|
233
|
+
* What matters is the size of the routing table.
|
|
218
234
|
* @param {number} timeoutMs - How long to wait.
|
|
219
|
-
* @returns {Promise<
|
|
235
|
+
* @returns {Promise<number | null>} - Nodes found, or null if unknowable.
|
|
220
236
|
*/
|
|
221
|
-
#whenDhtReady(timeoutMs) {
|
|
222
|
-
|
|
223
|
-
// A stand-in without an event emitter is ready by definition.
|
|
224
|
-
if (typeof this.#dht?.once !== 'function') return Promise.resolve(true);
|
|
237
|
+
async #whenDhtReady(timeoutMs) {
|
|
238
|
+
const deadline = Date.now() + timeoutMs;
|
|
225
239
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
240
|
+
if (typeof this.#dht?.once === 'function' && !this.#dht.ready) {
|
|
241
|
+
await new Promise((resolve) => {
|
|
242
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
243
|
+
timer.unref?.();
|
|
244
|
+
this.#dht.once('ready', () => {
|
|
245
|
+
clearTimeout(timer);
|
|
246
|
+
resolve();
|
|
247
|
+
});
|
|
232
248
|
});
|
|
233
|
-
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
let count = this.#nodeCount();
|
|
252
|
+
while (count === 0 && Date.now() < deadline && !this.#stopped) {
|
|
253
|
+
await new Promise((resolve) => {
|
|
254
|
+
const timer = setTimeout(resolve, 1000);
|
|
255
|
+
timer.unref?.();
|
|
256
|
+
});
|
|
257
|
+
count = this.#nodeCount();
|
|
258
|
+
}
|
|
259
|
+
return count;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* How many nodes the DHT currently knows, where it can say.
|
|
264
|
+
* @returns {number | null} - The count, or null for a stand-in that has none.
|
|
265
|
+
*/
|
|
266
|
+
#nodeCount() {
|
|
267
|
+
const count = this.#dht?.nodes?.count?.();
|
|
268
|
+
if (typeof count === 'number') return count;
|
|
269
|
+
const listed = this.#dht?.toJSON?.().nodes?.length;
|
|
270
|
+
return typeof listed === 'number' ? listed : null;
|
|
234
271
|
}
|
|
235
272
|
|
|
236
273
|
/**
|