@evanp/activitypub-bot 0.45.7 → 0.45.9
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 +13 -1
- package/lib/app.js +26 -0
- package/lib/distributionworker.js +25 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,7 +9,19 @@ and this project adheres to
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
-
## [0.45.
|
|
12
|
+
## [0.45.9] - 2026-04-29
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Don't infinitely retry on 429 status code.
|
|
17
|
+
|
|
18
|
+
## [0.45.8] - 2026-04-29
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Log memory usage.
|
|
23
|
+
|
|
24
|
+
## [0.45.7] - 2026-04-27
|
|
13
25
|
|
|
14
26
|
### Fixed
|
|
15
27
|
|
package/lib/app.js
CHANGED
|
@@ -2,6 +2,7 @@ import http from 'node:http'
|
|
|
2
2
|
import { resolve, dirname } from 'node:path'
|
|
3
3
|
import { fileURLToPath } from 'node:url'
|
|
4
4
|
import { randomUUID } from 'node:crypto'
|
|
5
|
+
import v8 from 'node:v8'
|
|
5
6
|
|
|
6
7
|
import { Sequelize } from 'sequelize'
|
|
7
8
|
import express from 'express'
|
|
@@ -69,6 +70,19 @@ export async function makeApp ({ databaseUrl, origin, bots, logLevel = 'silent',
|
|
|
69
70
|
level: logLevel
|
|
70
71
|
})
|
|
71
72
|
logger.debug('Logger initialized')
|
|
73
|
+
const memoryStatus = (message = 'memory', level = 'debug') => {
|
|
74
|
+
const mem = process.memoryUsage()
|
|
75
|
+
const heap = v8.getHeapStatistics()
|
|
76
|
+
logger[level]({
|
|
77
|
+
rss: mem.rss,
|
|
78
|
+
heapUsed: mem.heapUsed,
|
|
79
|
+
heapTotal: mem.heapTotal,
|
|
80
|
+
external: mem.external,
|
|
81
|
+
arrayBuffers: mem.arrayBuffers,
|
|
82
|
+
heapSizeLimit: heap.heap_size_limit
|
|
83
|
+
}, message)
|
|
84
|
+
}
|
|
85
|
+
memoryStatus('makeApp started')
|
|
72
86
|
const connection = databaseUrl === 'sqlite::memory:' || databaseUrl === 'sqlite::memory'
|
|
73
87
|
? new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
|
|
74
88
|
: new Sequelize(databaseUrl, { logging: false })
|
|
@@ -132,6 +146,8 @@ export async function makeApp ({ databaseUrl, origin, bots, logLevel = 'silent',
|
|
|
132
146
|
await redisClient.connect()
|
|
133
147
|
}
|
|
134
148
|
|
|
149
|
+
memoryStatus('services initialized')
|
|
150
|
+
|
|
135
151
|
await Promise.all(
|
|
136
152
|
Object.entries(bots).map(([key, bot]) => bot.initialize(
|
|
137
153
|
new BotContext(
|
|
@@ -169,6 +185,8 @@ export async function makeApp ({ databaseUrl, origin, bots, logLevel = 'silent',
|
|
|
169
185
|
bots
|
|
170
186
|
))
|
|
171
187
|
|
|
188
|
+
memoryStatus('bots initialized')
|
|
189
|
+
|
|
172
190
|
const { workers: deliveryWorkers, runs: deliveryWorkerRuns } = createWorkers(logger, deliveryWorkerCount, DeliveryWorker, jobQueue, logger, { actorStorage, activityHandler, bots })
|
|
173
191
|
const { workers: distributionWorkers, runs: distributionWorkerRuns } = createWorkers(logger, distributionWorkerCount, DistributionWorker, jobQueue, logger, { client })
|
|
174
192
|
const { workers: fanoutWorkers, runs: fanoutWorkerRuns } = createWorkers(logger, fanoutWorkerCount, FanoutWorker, jobQueue, logger, { distributor })
|
|
@@ -179,6 +197,11 @@ export async function makeApp ({ databaseUrl, origin, bots, logLevel = 'silent',
|
|
|
179
197
|
logger.error({ err }, 'unexpected error in job reaper')
|
|
180
198
|
})
|
|
181
199
|
|
|
200
|
+
memoryStatus('workers initialized')
|
|
201
|
+
|
|
202
|
+
const memInterval = setInterval(() => memoryStatus('memory', 'info'), 60_000)
|
|
203
|
+
memInterval.unref()
|
|
204
|
+
|
|
182
205
|
const app = express()
|
|
183
206
|
|
|
184
207
|
app.locals = {
|
|
@@ -415,8 +438,11 @@ export async function makeApp ({ databaseUrl, origin, bots, logLevel = 'silent',
|
|
|
415
438
|
}
|
|
416
439
|
logger.info('Closing database connection')
|
|
417
440
|
await connection.close()
|
|
441
|
+
clearInterval(memInterval)
|
|
418
442
|
logger.info('Done')
|
|
419
443
|
}
|
|
420
444
|
|
|
445
|
+
memoryStatus('app initialized', 'info')
|
|
446
|
+
|
|
421
447
|
return app
|
|
422
448
|
}
|
|
@@ -44,13 +44,21 @@ export class DistributionWorker extends Worker {
|
|
|
44
44
|
'Could not deliver activity due to client error'
|
|
45
45
|
)
|
|
46
46
|
if ([408, 425, 429].includes(err.status)) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
if (attempts >= DistributionWorker.#MAX_ATTEMPTS) {
|
|
48
|
+
this._logger.warn(
|
|
49
|
+
{ err, activity: activity.id, inbox, attempts },
|
|
50
|
+
'Could not deliver activity due to client error; no more attempts'
|
|
51
|
+
)
|
|
52
|
+
throw err
|
|
53
|
+
} else {
|
|
54
|
+
this._logger.debug(
|
|
55
|
+
{ err, activity: activity.id, inbox },
|
|
56
|
+
'Retrying on recoverable status'
|
|
57
|
+
)
|
|
58
|
+
const recoverable = new RecoverableError(err.message)
|
|
59
|
+
recoverable.delay = this.#retryDelay(err.headers, attempts)
|
|
60
|
+
throw recoverable
|
|
61
|
+
}
|
|
54
62
|
} else {
|
|
55
63
|
throw err
|
|
56
64
|
}
|
|
@@ -87,6 +95,12 @@ export class DistributionWorker extends Worker {
|
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
#retryDelay (headers, attempts) {
|
|
98
|
+
const headerDelay = this.#headerDelay(headers)
|
|
99
|
+
const attemptsDelay = this.#attemptsDelay(attempts)
|
|
100
|
+
return Math.max(headerDelay, attemptsDelay)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#headerDelay (headers) {
|
|
90
104
|
if (headers?.['retry-after']) {
|
|
91
105
|
this._logger.debug('using retry-after header')
|
|
92
106
|
const retryAfter = headers['retry-after']
|
|
@@ -96,7 +110,10 @@ export class DistributionWorker extends Worker {
|
|
|
96
110
|
return new Date(retryAfter) - Date.now()
|
|
97
111
|
}
|
|
98
112
|
}
|
|
99
|
-
|
|
113
|
+
return 0
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#attemptsDelay (attempts) {
|
|
100
117
|
return Math.round((2 ** (attempts - 1) * 1000) * (0.5 + Math.random()))
|
|
101
118
|
}
|
|
102
119
|
}
|