@evanp/activitypub-bot 0.45.14 → 0.45.15
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 +11 -0
- package/lib/jobqueue.js +6 -1
- package/lib/requestthrottler.js +6 -1
- package/lib/worker.js +11 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,17 @@ and this project adheres to
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.45.15] - 2026-05-11
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Heuristic to check if an integer in X-RateLimit-Reset is probably an offset or
|
|
17
|
+
probably a Unix epoch in seconds. Anything less than 30 days is treated as an
|
|
18
|
+
offset; otherwise it's an epoch.
|
|
19
|
+
- Fix job queue to clamp job retry delays between 0 and 30 days.
|
|
20
|
+
- Fix workers to continue operating even if retry or fail calls
|
|
21
|
+
fail.
|
|
22
|
+
|
|
12
23
|
## [0.45.14] - 2026-05-10
|
|
13
24
|
|
|
14
25
|
### Changed
|
package/lib/jobqueue.js
CHANGED
|
@@ -6,6 +6,7 @@ import { QueryTypes } from 'sequelize'
|
|
|
6
6
|
|
|
7
7
|
const MAX_DELAY = 30000
|
|
8
8
|
const DEFAULT_PRIORITY = 1000000
|
|
9
|
+
const MAX_RETRY = 30 * 24 * 60 * 60 * 1000
|
|
9
10
|
|
|
10
11
|
export class JobQueue {
|
|
11
12
|
#connection
|
|
@@ -94,7 +95,11 @@ export class JobQueue {
|
|
|
94
95
|
assert.strictEqual(typeof jobRunnerId, 'string')
|
|
95
96
|
assert.strictEqual(typeof delay, 'number')
|
|
96
97
|
|
|
97
|
-
const retryAfter =
|
|
98
|
+
const retryAfter = (isNaN(delay))
|
|
99
|
+
? new Date(Date.now() + 1000)
|
|
100
|
+
: (!isFinite(delay))
|
|
101
|
+
? new Date(Date.now() + MAX_RETRY)
|
|
102
|
+
: new Date(Date.now() + Math.max(0, Math.min(delay, MAX_RETRY)))
|
|
98
103
|
|
|
99
104
|
await this.#connection.query(`
|
|
100
105
|
UPDATE job
|
package/lib/requestthrottler.js
CHANGED
|
@@ -2,6 +2,7 @@ import { setTimeout as sleep } from 'node:timers/promises'
|
|
|
2
2
|
import assert from 'node:assert'
|
|
3
3
|
|
|
4
4
|
const BETA = 0.75
|
|
5
|
+
const EPOCH_THRESHOLD = 30 * 24 * 60 * 60
|
|
5
6
|
|
|
6
7
|
export class ThrottleError extends Error {
|
|
7
8
|
constructor (message, waitTime) {
|
|
@@ -51,7 +52,11 @@ export class RequestThrottler {
|
|
|
51
52
|
let reset
|
|
52
53
|
if (resetHeader.match(/^\d+$/)) {
|
|
53
54
|
resetSeconds = parseInt(resetHeader)
|
|
54
|
-
|
|
55
|
+
if (resetSeconds < EPOCH_THRESHOLD) {
|
|
56
|
+
reset = new Date(Date.now() + (resetSeconds * 1000))
|
|
57
|
+
} else {
|
|
58
|
+
reset = new Date(resetSeconds * 1000)
|
|
59
|
+
}
|
|
55
60
|
} else {
|
|
56
61
|
reset = new Date(resetHeader)
|
|
57
62
|
resetSeconds = reset - Date.now()
|
package/lib/worker.js
CHANGED
|
@@ -68,10 +68,17 @@ export class Worker {
|
|
|
68
68
|
await this.doJob(payload, attempts)
|
|
69
69
|
await this.#jobQueue.complete(jobId, this.#workerId)
|
|
70
70
|
} catch (err) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
try {
|
|
72
|
+
if (err instanceof RecoverableError) {
|
|
73
|
+
await this.#jobQueue.retryAfter(jobId, this.#workerId, err.delay, err.stack)
|
|
74
|
+
} else {
|
|
75
|
+
await this.#jobQueue.fail(jobId, this.#workerId, err.stack)
|
|
76
|
+
}
|
|
77
|
+
} catch (queueError) {
|
|
78
|
+
this.#logger.error(
|
|
79
|
+
{ err: queueError, original: err, jobId, workerId: this.#workerId },
|
|
80
|
+
'job retry/fail error'
|
|
81
|
+
)
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
}
|