@archlast/server 0.1.8 → 0.1.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.
Files changed (347) hide show
  1. package/README.md +104 -100
  2. package/dist/admin/auth.d.ts +24 -5
  3. package/dist/admin/auth.js +49 -25
  4. package/dist/admin/schema.d.ts +122 -32
  5. package/dist/admin/schema.js +131 -95
  6. package/dist/admin/seed.d.ts +1 -1
  7. package/dist/admin/seed.js +79 -47
  8. package/dist/auth/api-key-resolver.d.ts +1 -1
  9. package/dist/auth/api-key-resolver.js +7 -3
  10. package/dist/auth/archlast-auth-adapter.d.ts +2 -5
  11. package/dist/auth/archlast-auth-adapter.js +1 -1
  12. package/dist/auth/better-auth-adapter.d.ts.map +1 -1
  13. package/dist/auth/better-auth-adapter.js +41 -26
  14. package/dist/auth/better-auth-adapter.js.map +1 -1
  15. package/dist/auth/better-auth-admin.d.ts.map +1 -1
  16. package/dist/auth/better-auth-admin.js +1 -1
  17. package/dist/auth/better-auth-admin.js.map +1 -1
  18. package/dist/auth/better-auth-api-key-resolver.js +1 -1
  19. package/dist/auth/better-auth-api-key-resolver.js.map +1 -1
  20. package/dist/auth/better-auth-instance.d.ts +249 -301
  21. package/dist/auth/better-auth-instance.d.ts.map +1 -1
  22. package/dist/auth/better-auth-instance.js +11 -0
  23. package/dist/auth/better-auth-instance.js.map +1 -1
  24. package/dist/auth/better-auth-seed.d.ts +5 -2
  25. package/dist/auth/better-auth-seed.js +31 -22
  26. package/dist/auth/better-auth-session-adapter.d.ts.map +1 -1
  27. package/dist/auth/better-auth-session-adapter.js +14 -10
  28. package/dist/auth/better-auth-session-adapter.js.map +1 -1
  29. package/dist/auth/errors.d.ts.map +1 -1
  30. package/dist/auth/errors.js +11 -11
  31. package/dist/auth/errors.js.map +1 -1
  32. package/dist/auth/oauth-proxy.d.ts +5 -2
  33. package/dist/auth/oauth-proxy.js +23 -27
  34. package/dist/auth/resolver.d.ts.map +1 -1
  35. package/dist/auth/resolver.js.map +1 -1
  36. package/dist/auth/role-helpers.d.ts +1 -1
  37. package/dist/auth/role-helpers.d.ts.map +1 -1
  38. package/dist/auth/role-helpers.js.map +1 -1
  39. package/dist/auth/session-manager.d.ts +2 -5
  40. package/dist/auth/session-manager.js +16 -6
  41. package/dist/auth/system/better-auth-schema.d.ts.map +1 -1
  42. package/dist/auth/system/better-auth-schema.js +6 -23
  43. package/dist/auth/system/better-auth-schema.js.map +1 -1
  44. package/dist/cache/circuit-breaker.d.ts +81 -0
  45. package/dist/cache/circuit-breaker.d.ts.map +1 -0
  46. package/dist/cache/circuit-breaker.js +170 -0
  47. package/dist/cache/circuit-breaker.js.map +1 -0
  48. package/dist/cache/client.d.ts +6 -3
  49. package/dist/cache/client.d.ts.map +1 -1
  50. package/dist/cache/client.js +12 -53
  51. package/dist/cache/client.js.map +1 -1
  52. package/dist/cache/index.d.ts +2 -0
  53. package/dist/cache/index.d.ts.map +1 -1
  54. package/dist/cache/index.js +5 -1
  55. package/dist/cache/index.js.map +1 -1
  56. package/dist/cache/invalidation-queue.d.ts +63 -0
  57. package/dist/cache/invalidation-queue.d.ts.map +1 -0
  58. package/dist/cache/invalidation-queue.js +196 -0
  59. package/dist/cache/invalidation-queue.js.map +1 -0
  60. package/dist/cache/layers.d.ts +14 -4
  61. package/dist/cache/layers.d.ts.map +1 -1
  62. package/dist/cache/layers.js +66 -72
  63. package/dist/cache/layers.js.map +1 -1
  64. package/dist/cache/manager.d.ts.map +1 -1
  65. package/dist/cache/manager.js +6 -41
  66. package/dist/cache/manager.js.map +1 -1
  67. package/dist/cache/protocol.d.ts +4 -39
  68. package/dist/cache/protocol.d.ts.map +1 -1
  69. package/dist/cache/protocol.js.map +1 -1
  70. package/dist/cache/redis-adapter.d.ts +103 -0
  71. package/dist/cache/redis-adapter.d.ts.map +1 -0
  72. package/dist/cache/redis-adapter.js +424 -0
  73. package/dist/cache/redis-adapter.js.map +1 -0
  74. package/dist/cache/run-sidecar.js +10 -1
  75. package/dist/cache/run-sidecar.js.map +1 -1
  76. package/dist/cache/sidecar-server.d.ts +51 -1
  77. package/dist/cache/sidecar-server.d.ts.map +1 -1
  78. package/dist/cache/sidecar-server.js +368 -22
  79. package/dist/cache/sidecar-server.js.map +1 -1
  80. package/dist/cache/store.d.ts +43 -0
  81. package/dist/cache/store.d.ts.map +1 -1
  82. package/dist/cache/store.js +69 -76
  83. package/dist/cache/store.js.map +1 -1
  84. package/dist/cache/strategies.d.ts +2 -9
  85. package/dist/cache/strategies.d.ts.map +1 -1
  86. package/dist/cache/types.d.ts +130 -0
  87. package/dist/cache/types.d.ts.map +1 -0
  88. package/dist/cache/types.js +60 -0
  89. package/dist/cache/types.js.map +1 -0
  90. package/dist/config/bullmq.d.ts +16 -0
  91. package/dist/config/bullmq.d.ts.map +1 -0
  92. package/dist/config/bullmq.js +103 -0
  93. package/dist/config/bullmq.js.map +1 -0
  94. package/dist/config/index.d.ts +1 -0
  95. package/dist/config/index.d.ts.map +1 -1
  96. package/dist/config/index.js +1 -0
  97. package/dist/config/index.js.map +1 -1
  98. package/dist/config/schema.d.ts +80 -6
  99. package/dist/config/schema.d.ts.map +1 -1
  100. package/dist/config/schema.js +71 -6
  101. package/dist/config/schema.js.map +1 -1
  102. package/dist/config/service.d.ts +54 -4
  103. package/dist/config/service.d.ts.map +1 -1
  104. package/dist/config/service.js +56 -2
  105. package/dist/config/service.js.map +1 -1
  106. package/dist/controllers/admin/admin-tokens.controller.d.ts +131 -115
  107. package/dist/controllers/admin/admin-tokens.controller.js +117 -98
  108. package/dist/controllers/admin/api-keys.controller.d.ts +1 -1
  109. package/dist/controllers/admin/api-keys.controller.d.ts.map +1 -1
  110. package/dist/controllers/admin/api-keys.controller.js.map +1 -1
  111. package/dist/controllers/admin/app-users.controller.d.ts +274 -243
  112. package/dist/controllers/admin/app-users.controller.js +301 -257
  113. package/dist/controllers/admin/auth.controller.d.ts +260 -236
  114. package/dist/controllers/admin/auth.controller.js +197 -174
  115. package/dist/controllers/admin/backup.controller.d.ts.map +1 -1
  116. package/dist/controllers/admin/backup.controller.js.map +1 -1
  117. package/dist/controllers/admin/settings.controller.d.ts +1 -1
  118. package/dist/controllers/admin/storage-stats.controller.d.ts +63 -0
  119. package/dist/controllers/admin/storage-stats.controller.d.ts.map +1 -0
  120. package/dist/controllers/admin/storage-stats.controller.js +33 -0
  121. package/dist/controllers/admin/storage-stats.controller.js.map +1 -0
  122. package/dist/controllers/admin/tenants.controller.d.ts.map +1 -1
  123. package/dist/controllers/admin/tenants.controller.js.map +1 -1
  124. package/dist/controllers/admin/users.controller.d.ts +1 -1
  125. package/dist/controllers/admin/users.controller.d.ts.map +1 -1
  126. package/dist/controllers/admin/users.controller.js.map +1 -1
  127. package/dist/controllers/auth.controller.d.ts +289 -271
  128. package/dist/controllers/auth.controller.js +275 -226
  129. package/dist/controllers/crud-generator.controller.d.ts.map +1 -1
  130. package/dist/controllers/crud-generator.controller.js +127 -125
  131. package/dist/controllers/crud-generator.controller.js.map +1 -1
  132. package/dist/controllers/index.d.ts +1 -1
  133. package/dist/controllers/index.d.ts.map +1 -1
  134. package/dist/controllers/index.js.map +1 -1
  135. package/dist/controllers/introspection.controller.d.ts +642 -0
  136. package/dist/controllers/introspection.controller.d.ts.map +1 -1
  137. package/dist/controllers/introspection.controller.js +611 -0
  138. package/dist/controllers/introspection.controller.js.map +1 -1
  139. package/dist/controllers/invite.controller.d.ts +190 -170
  140. package/dist/controllers/invite.controller.js +183 -164
  141. package/dist/controllers/mfa.controller.d.ts +205 -183
  142. package/dist/controllers/mfa.controller.js +131 -111
  143. package/dist/controllers/otp.controller.d.ts +194 -171
  144. package/dist/controllers/otp.controller.js +192 -175
  145. package/dist/controllers/storage.controller.d.ts.map +1 -1
  146. package/dist/controllers/storage.controller.js.map +1 -1
  147. package/dist/controllers/system.controller.d.ts +5 -3
  148. package/dist/controllers/system.controller.d.ts.map +1 -1
  149. package/dist/controllers/system.controller.js +4 -2
  150. package/dist/controllers/system.controller.js.map +1 -1
  151. package/dist/controllers/tenant.controller.d.ts +258 -227
  152. package/dist/controllers/tenant.controller.js +224 -200
  153. package/dist/db/cachedclient.d.ts +6 -11
  154. package/dist/db/cachedclient.d.ts.map +1 -1
  155. package/dist/db/cachedclient.js +79 -43
  156. package/dist/db/cachedclient.js.map +1 -1
  157. package/dist/db/distributed-client.d.ts +79 -24
  158. package/dist/db/distributed-client.js +23 -24
  159. package/dist/db/factory.d.ts +3 -8
  160. package/dist/db/factory.d.ts.map +1 -1
  161. package/dist/db/factory.js +3 -22
  162. package/dist/db/factory.js.map +1 -1
  163. package/dist/db/socket-client.d.ts +7 -0
  164. package/dist/db/socket-client.d.ts.map +1 -1
  165. package/dist/db/socket-client.js +140 -11
  166. package/dist/db/socket-client.js.map +1 -1
  167. package/dist/deployment/handler.d.ts +10 -2
  168. package/dist/deployment/handler.d.ts.map +1 -1
  169. package/dist/deployment/handler.js +70 -15
  170. package/dist/deployment/handler.js.map +1 -1
  171. package/dist/deployment/persistence.d.ts.map +1 -1
  172. package/dist/deployment/persistence.js +6 -1
  173. package/dist/deployment/persistence.js.map +1 -1
  174. package/dist/docker/compose.d.ts.map +1 -1
  175. package/dist/docker/compose.js +76 -0
  176. package/dist/docker/compose.js.map +1 -1
  177. package/dist/engine/runner.d.ts.map +1 -1
  178. package/dist/engine/runner.js +0 -43
  179. package/dist/engine/runner.js.map +1 -1
  180. package/dist/functions/built-in/auth-apikey.d.ts.map +1 -1
  181. package/dist/functions/built-in/auth-apikey.js.map +1 -1
  182. package/dist/functions/built-in/system-cache.d.ts.map +1 -1
  183. package/dist/functions/built-in/system-cache.js +6 -31
  184. package/dist/functions/built-in/system-cache.js.map +1 -1
  185. package/dist/functions/built-in/system-data.d.ts.map +1 -1
  186. package/dist/functions/built-in/system-data.js +4 -2
  187. package/dist/functions/built-in/system-data.js.map +1 -1
  188. package/dist/functions/definition.d.ts.map +1 -1
  189. package/dist/functions/definition.js +6 -2
  190. package/dist/functions/definition.js.map +1 -1
  191. package/dist/http/routes/metrics.d.ts +42 -0
  192. package/dist/http/routes/metrics.d.ts.map +1 -0
  193. package/dist/http/routes/metrics.js +29 -0
  194. package/dist/http/routes/metrics.js.map +1 -0
  195. package/dist/http/server.d.ts +1 -0
  196. package/dist/http/server.d.ts.map +1 -1
  197. package/dist/http/server.js +41 -3
  198. package/dist/http/server.js.map +1 -1
  199. package/dist/ipc/socket-bridge.d.ts +1 -0
  200. package/dist/ipc/socket-bridge.d.ts.map +1 -1
  201. package/dist/ipc/socket-bridge.js +5 -1
  202. package/dist/ipc/socket-bridge.js.map +1 -1
  203. package/dist/jobs/bullmq-adapter.d.ts +154 -0
  204. package/dist/jobs/bullmq-adapter.d.ts.map +1 -0
  205. package/dist/jobs/bullmq-adapter.js +688 -0
  206. package/dist/jobs/bullmq-adapter.js.map +1 -0
  207. package/dist/jobs/bullmq-circuit-breaker.d.ts +133 -0
  208. package/dist/jobs/bullmq-circuit-breaker.d.ts.map +1 -0
  209. package/dist/jobs/bullmq-circuit-breaker.js +323 -0
  210. package/dist/jobs/bullmq-circuit-breaker.js.map +1 -0
  211. package/dist/jobs/bullmq-dlq-manager.d.ts +155 -0
  212. package/dist/jobs/bullmq-dlq-manager.d.ts.map +1 -0
  213. package/dist/jobs/bullmq-dlq-manager.js +325 -0
  214. package/dist/jobs/bullmq-dlq-manager.js.map +1 -0
  215. package/dist/jobs/bullmq-metrics.d.ts +104 -0
  216. package/dist/jobs/bullmq-metrics.d.ts.map +1 -0
  217. package/dist/jobs/bullmq-metrics.js +323 -0
  218. package/dist/jobs/bullmq-metrics.js.map +1 -0
  219. package/dist/jobs/bullmq-priority-service.d.ts +173 -0
  220. package/dist/jobs/bullmq-priority-service.d.ts.map +1 -0
  221. package/dist/jobs/bullmq-priority-service.js +390 -0
  222. package/dist/jobs/bullmq-priority-service.js.map +1 -0
  223. package/dist/jobs/bullmq-scheduler.d.ts +111 -0
  224. package/dist/jobs/bullmq-scheduler.d.ts.map +1 -0
  225. package/dist/jobs/bullmq-scheduler.js +300 -0
  226. package/dist/jobs/bullmq-scheduler.js.map +1 -0
  227. package/dist/jobs/bullmq-worker.d.ts +155 -0
  228. package/dist/jobs/bullmq-worker.d.ts.map +1 -0
  229. package/dist/jobs/bullmq-worker.js +651 -0
  230. package/dist/jobs/bullmq-worker.js.map +1 -0
  231. package/dist/jobs/circuit-breaker.d.ts +120 -0
  232. package/dist/jobs/circuit-breaker.d.ts.map +1 -0
  233. package/dist/jobs/circuit-breaker.js +262 -0
  234. package/dist/jobs/circuit-breaker.js.map +1 -0
  235. package/dist/jobs/index.d.ts +1 -1
  236. package/dist/jobs/index.d.ts.map +1 -1
  237. package/dist/jobs/index.js.map +1 -1
  238. package/dist/jobs/queue.d.ts +120 -1
  239. package/dist/jobs/queue.d.ts.map +1 -1
  240. package/dist/jobs/queue.js +487 -9
  241. package/dist/jobs/queue.js.map +1 -1
  242. package/dist/jobs/redis-connection.d.ts +50 -0
  243. package/dist/jobs/redis-connection.d.ts.map +1 -0
  244. package/dist/jobs/redis-connection.js +123 -0
  245. package/dist/jobs/redis-connection.js.map +1 -0
  246. package/dist/jobs/run-scheduler.js +163 -10
  247. package/dist/jobs/run-scheduler.js.map +1 -1
  248. package/dist/jobs/run-worker.js +101 -9
  249. package/dist/jobs/run-worker.js.map +1 -1
  250. package/dist/jobs/worker-thread.d.ts +6 -0
  251. package/dist/jobs/worker-thread.d.ts.map +1 -1
  252. package/dist/jobs/worker-thread.js +37 -8
  253. package/dist/jobs/worker-thread.js.map +1 -1
  254. package/dist/jobs/worker.d.ts +33 -0
  255. package/dist/jobs/worker.d.ts.map +1 -1
  256. package/dist/jobs/worker.js +358 -115
  257. package/dist/jobs/worker.js.map +1 -1
  258. package/dist/linq/async-enumerable.d.ts.map +1 -1
  259. package/dist/linq/async-enumerable.js.map +1 -1
  260. package/dist/linq/enumerable.d.ts.map +1 -1
  261. package/dist/linq/enumerable.js +10 -10
  262. package/dist/linq/enumerable.js.map +1 -1
  263. package/dist/metrics/collector.d.ts +26 -0
  264. package/dist/metrics/collector.d.ts.map +1 -0
  265. package/dist/metrics/collector.js +103 -0
  266. package/dist/metrics/collector.js.map +1 -0
  267. package/dist/polling/updates.controller.d.ts +57 -0
  268. package/dist/polling/updates.controller.d.ts.map +1 -0
  269. package/dist/polling/updates.controller.js +70 -0
  270. package/dist/polling/updates.controller.js.map +1 -0
  271. package/dist/repository/db-set.d.ts.map +1 -1
  272. package/dist/repository/db-set.js +12 -8
  273. package/dist/repository/db-set.js.map +1 -1
  274. package/dist/repository/ef-core.d.ts.map +1 -1
  275. package/dist/repository/ef-core.js +6 -6
  276. package/dist/repository/ef-core.js.map +1 -1
  277. package/dist/repository/factory.d.ts +1 -1
  278. package/dist/repository/factory.d.ts.map +1 -1
  279. package/dist/repository/factory.js.map +1 -1
  280. package/dist/repository/interfaces.d.ts.map +1 -1
  281. package/dist/repository/interfaces.js.map +1 -1
  282. package/dist/repository/queryable.d.ts.map +1 -1
  283. package/dist/repository/queryable.js.map +1 -1
  284. package/dist/rpc/adapter.d.ts.map +1 -1
  285. package/dist/rpc/adapter.js.map +1 -1
  286. package/dist/rpc/router.d.ts +2 -2
  287. package/dist/rpc/router.d.ts.map +1 -1
  288. package/dist/rpc/router.js +1 -1
  289. package/dist/rpc/router.js.map +1 -1
  290. package/dist/schema/relationship-types.d.ts +7 -2
  291. package/dist/schema/relationship-types.js +1 -1
  292. package/dist/schema/types.d.ts.map +1 -1
  293. package/dist/services/admin/app-users.service.d.ts +1 -1
  294. package/dist/services/admin/app-users.service.js +31 -38
  295. package/dist/services/admin/auth.service.d.ts +1 -1
  296. package/dist/services/admin/auth.service.js +11 -5
  297. package/dist/services/admin/backup/BackupOrchestrator.d.ts.map +1 -1
  298. package/dist/services/admin/backup/BackupOrchestrator.js +4 -7
  299. package/dist/services/admin/backup/BackupOrchestrator.js.map +1 -1
  300. package/dist/services/admin/backup/SqliteGenerator.js +8 -8
  301. package/dist/services/admin/backup/StorageStreamer.d.ts +3 -3
  302. package/dist/services/admin/backup/StorageStreamer.d.ts.map +1 -1
  303. package/dist/services/admin/backup/StorageStreamer.js +16 -55
  304. package/dist/services/admin/backup/StorageStreamer.js.map +1 -1
  305. package/dist/services/admin/backup/ZipComposer.d.ts +2 -0
  306. package/dist/services/admin/backup/ZipComposer.d.ts.map +1 -1
  307. package/dist/services/admin/backup/ZipComposer.js +23 -0
  308. package/dist/services/admin/backup/ZipComposer.js.map +1 -1
  309. package/dist/services/admin/backup.service.d.ts.map +1 -1
  310. package/dist/services/admin/backup.service.js.map +1 -1
  311. package/dist/services/admin/data.service.d.ts.map +1 -1
  312. package/dist/services/admin/data.service.js +287 -286
  313. package/dist/services/admin/data.service.js.map +1 -1
  314. package/dist/services/admin/tenants.service.d.ts.map +1 -1
  315. package/dist/services/admin/tenants.service.js.map +1 -1
  316. package/dist/services/auth.service.d.ts +2 -3
  317. package/dist/services/auth.service.js +16 -16
  318. package/dist/services/invite.service.d.ts +1 -1
  319. package/dist/services/invite.service.js +17 -15
  320. package/dist/services/storage.service.d.ts.map +1 -1
  321. package/dist/services/storage.service.js +35 -4
  322. package/dist/services/storage.service.js.map +1 -1
  323. package/dist/services/system.service.d.ts.map +1 -1
  324. package/dist/services/system.service.js +1 -1
  325. package/dist/services/system.service.js.map +1 -1
  326. package/dist/services/tenant.service.d.ts +1 -1
  327. package/dist/services/tenant.service.js +43 -31
  328. package/dist/sse/subscriptions.controller.d.ts +57 -0
  329. package/dist/sse/subscriptions.controller.d.ts.map +1 -0
  330. package/dist/sse/subscriptions.controller.js +127 -0
  331. package/dist/sse/subscriptions.controller.js.map +1 -0
  332. package/dist/startup/bootstrap.d.ts +13 -2
  333. package/dist/startup/bootstrap.d.ts.map +1 -1
  334. package/dist/startup/bootstrap.js +85 -13
  335. package/dist/startup/bootstrap.js.map +1 -1
  336. package/dist/storage/s3-backend.d.ts.map +1 -1
  337. package/dist/storage/s3-backend.js +3 -3
  338. package/dist/storage/s3-backend.js.map +1 -1
  339. package/dist/websocket/server.d.ts.map +1 -1
  340. package/dist/websocket/server.js +14 -3
  341. package/dist/websocket/server.js.map +1 -1
  342. package/docker/README.md +309 -11
  343. package/package.json +214 -210
  344. package/templates/.env.example +115 -55
  345. package/templates/archlast.config.js +51 -37
  346. package/templates/docker-compose.prod.yml +32 -15
  347. package/templates/docker-compose.yml +117 -33
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BullMQMetricsCollector = void 0;
4
+ exports.setupBullMQPrometheusExporter = setupBullMQPrometheusExporter;
5
+ const bullmq_1 = require("bullmq");
6
+ const prom_client_1 = require("prom-client");
7
+ /**
8
+ * Collects metrics from BullMQ queues and exports to Prometheus.
9
+ * Tracks job lifecycle events, processing times, and queue state.
10
+ */
11
+ class BullMQMetricsCollector {
12
+ queueEvents = null;
13
+ metrics;
14
+ startTimes;
15
+ queue;
16
+ gaugeUpdateInterval = null;
17
+ options;
18
+ // Prometheus metrics
19
+ prometheusMetrics = null;
20
+ constructor(queueName, connection, options = {}) {
21
+ this.options = {
22
+ prometheusRegistry: options.prometheusRegistry ?? new prom_client_1.Registry(),
23
+ enableHistograms: options.enableHistograms ?? true,
24
+ gaugeUpdateIntervalMs: options.gaugeUpdateIntervalMs ?? 10000,
25
+ };
26
+ this.queue = new bullmq_1.Queue(queueName, { connection });
27
+ this.startTimes = new Map();
28
+ this.metrics = this.createEmptyMetrics();
29
+ this.setupPrometheusMetrics();
30
+ }
31
+ /**
32
+ * Creates an empty metrics object with initial values
33
+ */
34
+ createEmptyMetrics() {
35
+ return {
36
+ jobsCompleted: 0,
37
+ jobsFailed: 0,
38
+ jobsDelayed: 0,
39
+ jobsStalled: 0,
40
+ processingTimeMs: [],
41
+ queueWaitTimeMs: [],
42
+ pendingJobs: 0,
43
+ activeJobs: 0,
44
+ completedJobs: 0,
45
+ failedJobs: 0,
46
+ delayedJobs: 0,
47
+ errorTypes: {},
48
+ };
49
+ }
50
+ /**
51
+ * Sets up Prometheus metrics with the registry
52
+ */
53
+ setupPrometheusMetrics() {
54
+ const register = this.options.prometheusRegistry;
55
+ this.prometheusMetrics = {
56
+ jobsCompleted: new prom_client_1.Counter({
57
+ name: "archlast_jobs_completed_total",
58
+ help: "Total number of completed jobs",
59
+ labelNames: ["queue", "job_name"],
60
+ registers: [register],
61
+ }),
62
+ jobsFailed: new prom_client_1.Counter({
63
+ name: "archlast_jobs_failed_total",
64
+ help: "Total number of failed jobs",
65
+ labelNames: ["queue", "job_name", "error_type"],
66
+ registers: [register],
67
+ }),
68
+ jobsRetried: new prom_client_1.Counter({
69
+ name: "archlast_jobs_retried_total",
70
+ help: "Total number of job retries",
71
+ labelNames: ["queue", "job_name"],
72
+ registers: [register],
73
+ }),
74
+ jobsTimedOut: new prom_client_1.Counter({
75
+ name: "archlast_jobs_timed_out_total",
76
+ help: "Total number of jobs that timed out",
77
+ labelNames: ["queue", "job_name"],
78
+ registers: [register],
79
+ }),
80
+ jobsPending: new prom_client_1.Gauge({
81
+ name: "archlast_jobs_pending",
82
+ help: "Number of jobs currently pending",
83
+ labelNames: ["queue"],
84
+ registers: [register],
85
+ }),
86
+ jobsActive: new prom_client_1.Gauge({
87
+ name: "archlast_jobs_active",
88
+ help: "Number of jobs currently being processed",
89
+ labelNames: ["queue"],
90
+ registers: [register],
91
+ }),
92
+ jobsInDLQ: new prom_client_1.Gauge({
93
+ name: "archlast_jobs_dlq_total",
94
+ help: "Number of jobs in dead letter queue",
95
+ labelNames: ["queue"],
96
+ registers: [register],
97
+ }),
98
+ jobDuration: new prom_client_1.Histogram({
99
+ name: "archlast_job_duration_seconds",
100
+ help: "Job processing duration in seconds",
101
+ labelNames: ["queue", "job_name"],
102
+ buckets: [0.1, 0.5, 1, 2, 5, 10, 30, 60],
103
+ registers: [register],
104
+ }),
105
+ jobQueueWait: new prom_client_1.Histogram({
106
+ name: "archlast_job_queue_wait_seconds",
107
+ help: "Time jobs spent waiting in queue",
108
+ labelNames: ["queue", "job_name"],
109
+ buckets: [1, 10, 60, 300, 600, 1800, 3600],
110
+ registers: [register],
111
+ }),
112
+ };
113
+ }
114
+ /**
115
+ * Categorizes error messages into types for metrics
116
+ */
117
+ categorizeError(reason) {
118
+ if (!reason)
119
+ return "unknown";
120
+ const lowerReason = reason.toLowerCase();
121
+ if (lowerReason.includes("timeout"))
122
+ return "timeout";
123
+ if (lowerReason.includes("econnrefused") ||
124
+ lowerReason.includes("etimedout") ||
125
+ lowerReason.includes("enotfound"))
126
+ return "network";
127
+ if (lowerReason.includes("validation") || lowerReason.includes("invalid"))
128
+ return "validation";
129
+ if (lowerReason.includes("circuit"))
130
+ return "circuit_breaker";
131
+ if (lowerReason.includes("rate limit") || lowerReason.includes("ratelimit"))
132
+ return "rate_limit";
133
+ if (lowerReason.includes("unauthorized") || lowerReason.includes("forbidden"))
134
+ return "auth";
135
+ return "unknown";
136
+ }
137
+ /**
138
+ * Gets the job name from the job object or returns 'unknown'
139
+ */
140
+ getJobName(job) {
141
+ return job.name ?? job.data?.name ?? "unknown";
142
+ }
143
+ /**
144
+ * Starts collecting metrics from the queue.
145
+ * Sets up event listeners and begins periodic gauge updates.
146
+ */
147
+ async start() {
148
+ if (this.queueEvents) {
149
+ throw new Error("Metrics collector is already started");
150
+ }
151
+ // Create QueueEvents instance for listening to queue events
152
+ this.queueEvents = new bullmq_1.QueueEvents(this.queue.name, {
153
+ connection: this.queue.opts?.connection,
154
+ });
155
+ // Set up event listeners
156
+ this.queueEvents.on("completed", async ({ jobId, returnvalue }) => {
157
+ this.metrics.jobsCompleted++;
158
+ const startTime = this.startTimes.get(jobId);
159
+ if (startTime) {
160
+ const processingTime = Date.now() - startTime;
161
+ this.metrics.processingTimeMs.push(processingTime);
162
+ this.startTimes.delete(jobId);
163
+ // Update Prometheus histogram if enabled
164
+ if (this.prometheusMetrics && this.options.enableHistograms) {
165
+ const job = await this.queue.getJob(jobId);
166
+ const jobName = this.getJobName(job ?? {});
167
+ this.prometheusMetrics.jobDuration.observe({ queue: this.queue.name, job_name: jobName }, processingTime / 1000 // Convert to seconds
168
+ );
169
+ }
170
+ }
171
+ // Update Prometheus counter
172
+ if (this.prometheusMetrics) {
173
+ const job = await this.queue.getJob(jobId);
174
+ const jobName = this.getJobName(job ?? {});
175
+ this.prometheusMetrics.jobsCompleted.inc({
176
+ queue: this.queue.name,
177
+ job_name: jobName,
178
+ });
179
+ }
180
+ });
181
+ this.queueEvents.on("failed", async ({ jobId, failedReason }) => {
182
+ this.metrics.jobsFailed++;
183
+ const errorType = this.categorizeError(failedReason);
184
+ this.metrics.errorTypes[errorType] = (this.metrics.errorTypes[errorType] || 0) + 1;
185
+ this.startTimes.delete(jobId);
186
+ // Update Prometheus counter
187
+ if (this.prometheusMetrics) {
188
+ const job = await this.queue.getJob(jobId);
189
+ const jobName = this.getJobName(job ?? {});
190
+ this.prometheusMetrics.jobsFailed.inc({
191
+ queue: this.queue.name,
192
+ job_name: jobName,
193
+ error_type: errorType,
194
+ });
195
+ }
196
+ });
197
+ this.queueEvents.on("stalled", ({ jobId }) => {
198
+ this.metrics.jobsStalled++;
199
+ });
200
+ this.queueEvents.on("active", ({ jobId, prev }) => {
201
+ this.startTimes.set(jobId, Date.now());
202
+ // Track queue wait time if we have previous state
203
+ if (prev === "waiting" && this.prometheusMetrics) {
204
+ this.queue
205
+ .getJob(jobId)
206
+ .then((job) => {
207
+ if (job && job.timestamp) {
208
+ const waitTime = Date.now() - job.timestamp;
209
+ this.metrics.queueWaitTimeMs.push(waitTime);
210
+ if (this.options.enableHistograms) {
211
+ const jobName = this.getJobName(job);
212
+ this.prometheusMetrics?.jobQueueWait.observe({ queue: this.queue.name, job_name: jobName }, waitTime / 1000 // Convert to seconds
213
+ );
214
+ }
215
+ }
216
+ })
217
+ .catch(() => {
218
+ // Ignore errors when getting job for metrics
219
+ });
220
+ }
221
+ });
222
+ this.queueEvents.on("delayed", ({ jobId }) => {
223
+ this.metrics.jobsDelayed++;
224
+ });
225
+ this.queueEvents.on("retries-exhausted", async ({ jobId }) => {
226
+ if (this.prometheusMetrics) {
227
+ const job = await this.queue.getJob(jobId);
228
+ const jobName = this.getJobName(job ?? {});
229
+ this.prometheusMetrics.jobsTimedOut.inc({
230
+ queue: this.queue.name,
231
+ job_name: jobName,
232
+ });
233
+ }
234
+ });
235
+ // Set up periodic gauge updates
236
+ await this.updateGauges();
237
+ this.gaugeUpdateInterval = setInterval(() => this.updateGauges(), this.options.gaugeUpdateIntervalMs);
238
+ }
239
+ /**
240
+ * Stops collecting metrics and cleans up resources.
241
+ */
242
+ async stop() {
243
+ // Clear the gauge update interval
244
+ if (this.gaugeUpdateInterval) {
245
+ clearInterval(this.gaugeUpdateInterval);
246
+ this.gaugeUpdateInterval = null;
247
+ }
248
+ // Close QueueEvents
249
+ if (this.queueEvents) {
250
+ await this.queueEvents.close();
251
+ this.queueEvents = null;
252
+ }
253
+ // Close the queue connection
254
+ await this.queue.close();
255
+ }
256
+ /**
257
+ * Gets a snapshot of the current metrics.
258
+ */
259
+ getMetrics() {
260
+ return { ...this.metrics };
261
+ }
262
+ /**
263
+ * Resets all metrics to their initial values.
264
+ */
265
+ reset() {
266
+ this.metrics = this.createEmptyMetrics();
267
+ this.startTimes.clear();
268
+ }
269
+ /**
270
+ * Updates gauge values by fetching current queue state.
271
+ */
272
+ async updateGauges() {
273
+ try {
274
+ const counts = await this.queue.getJobCounts("waiting", "active", "completed", "failed", "delayed");
275
+ this.metrics.pendingJobs = counts.waiting;
276
+ this.metrics.activeJobs = counts.active;
277
+ this.metrics.completedJobs = counts.completed;
278
+ this.metrics.failedJobs = counts.failed;
279
+ this.metrics.delayedJobs = counts.delayed;
280
+ // Update Prometheus gauges
281
+ if (this.prometheusMetrics) {
282
+ this.prometheusMetrics.jobsPending.set({ queue: this.queue.name }, counts.waiting);
283
+ this.prometheusMetrics.jobsActive.set({ queue: this.queue.name }, counts.active);
284
+ this.prometheusMetrics.jobsInDLQ.set({ queue: this.queue.name }, counts.failed);
285
+ }
286
+ }
287
+ catch (error) {
288
+ // Silently ignore gauge update errors to prevent metric collection
289
+ // from affecting the main application
290
+ }
291
+ }
292
+ /**
293
+ * Gets the Prometheus registry associated with this collector.
294
+ */
295
+ getPrometheusRegistry() {
296
+ return this.options.prometheusRegistry;
297
+ }
298
+ }
299
+ exports.BullMQMetricsCollector = BullMQMetricsCollector;
300
+ /**
301
+ * Convenience function to set up a BullMQ metrics collector with Prometheus export.
302
+ *
303
+ * @param queueName - Name of the BullMQ queue to monitor
304
+ * @param connection - Redis connection (optional, will create default if not provided)
305
+ * @param register - Prometheus registry to use
306
+ * @returns Configured BullMQMetricsCollector instance
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * const collector = setupBullMQPrometheusExporter('my-queue', redis, register);
311
+ * await collector.start();
312
+ *
313
+ * // Later...
314
+ * await collector.stop();
315
+ * ```
316
+ */
317
+ function setupBullMQPrometheusExporter(queueName, connection, register) {
318
+ return new BullMQMetricsCollector(queueName, connection, {
319
+ prometheusRegistry: register,
320
+ enableHistograms: true,
321
+ });
322
+ }
323
+ //# sourceMappingURL=bullmq-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bullmq-metrics.js","sourceRoot":"","sources":["../../src/jobs/bullmq-metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ import Redis from "ioredis";
2
+ /**
3
+ * Aging metadata tracked for each job to prevent priority starvation.
4
+ * Stored within the job data under the `__aging__` key.
5
+ */
6
+ export interface AgingJobData {
7
+ /** Original priority as set by user (1-20, where 1 is highest priority) */
8
+ originalPriority: number;
9
+ /** Current aging bonus (0-5), increases the longer a job waits */
10
+ agingBonus: number;
11
+ /** Timestamp when job was created */
12
+ createdAt: number;
13
+ /** Timestamp of last aging check */
14
+ lastAgingCheck: number;
15
+ }
16
+ /**
17
+ * Options for configuring the priority aging service.
18
+ */
19
+ interface PriorityAgingServiceOptions {
20
+ /** How often to check for aging in milliseconds (default: 60000) */
21
+ checkIntervalMs?: number;
22
+ /** Maximum jobs to process per check (default: 100) */
23
+ maxJobsPerCheck?: number;
24
+ }
25
+ /**
26
+ * Service that implements priority aging for BullMQ jobs.
27
+ *
28
+ * Priority aging prevents job starvation by boosting the priority of jobs
29
+ * that have been waiting in the queue for an extended period. Every 15 minutes,
30
+ * a job's priority is increased by 1 level (up to a maximum bonus of 5).
31
+ *
32
+ * This service runs a background worker that periodically scans waiting jobs
33
+ * and updates their priorities based on their wait time.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const agingService = new BullMQPriorityAgingService(
38
+ * "my-queue",
39
+ * redisConnection,
40
+ * { checkIntervalMs: 60000 }
41
+ * );
42
+ *
43
+ * await agingService.start();
44
+ *
45
+ * // When enqueueing jobs, prepare data with aging metadata:
46
+ * const jobData = BullMQPriorityAgingService.prepareJobData(payload, priority);
47
+ * await queue.add("job-name", jobData, { priority: toBullMQPriority(priority) });
48
+ * ```
49
+ */
50
+ export declare class BullMQPriorityAgingService {
51
+ private readonly AGING_INTERVAL_MS;
52
+ private readonly MAX_AGING_BONUS;
53
+ private readonly DEFAULT_CHECK_INTERVAL_MS;
54
+ private readonly DEFAULT_MAX_JOBS_PER_CHECK;
55
+ private queue;
56
+ private agingWorker;
57
+ private workerConnection;
58
+ private checkIntervalMs;
59
+ private maxJobsPerCheck;
60
+ private queueName;
61
+ private connection;
62
+ private _isRunning;
63
+ private agingInterval;
64
+ /**
65
+ * Creates a new BullMQPriorityAgingService instance.
66
+ *
67
+ * @param queueName - The name of the BullMQ queue to monitor
68
+ * @param connection - Redis connection for BullMQ
69
+ * @param options - Optional configuration for the aging service
70
+ */
71
+ constructor(queueName: string, connection: Redis, options?: PriorityAgingServiceOptions);
72
+ /**
73
+ * Start the priority aging service.
74
+ *
75
+ * This creates a background worker that periodically checks waiting jobs
76
+ * and applies priority boosts to jobs that have been waiting too long.
77
+ *
78
+ * @returns Promise that resolves when the service is started
79
+ */
80
+ start(): Promise<void>;
81
+ /**
82
+ * Stop the priority aging service.
83
+ *
84
+ * Closes the aging worker and clears the check interval.
85
+ *
86
+ * @returns Promise that resolves when the service is stopped
87
+ */
88
+ stop(): Promise<void>;
89
+ /**
90
+ * Check if the aging service is currently running.
91
+ *
92
+ * @returns true if the service is running, false otherwise
93
+ */
94
+ isRunning(): boolean;
95
+ /**
96
+ * Manually trigger an aging check.
97
+ *
98
+ * This method scans waiting jobs, calculates their effective priority based on
99
+ * wait time, and updates job priorities if the aging bonus has increased.
100
+ *
101
+ * @returns Statistics about the aging check
102
+ */
103
+ applyAging(): Promise<{
104
+ jobsChecked: number;
105
+ jobsBoosted: number;
106
+ averageWaitTimeMs: number;
107
+ }>;
108
+ /**
109
+ * Calculate the effective priority for a job based on its base priority and creation time.
110
+ *
111
+ * The aging algorithm adds 1 priority level for every 15 minutes of wait time,
112
+ * up to a maximum bonus of 5 levels.
113
+ *
114
+ * @param basePriority - The original priority (1-20, where 1 is highest)
115
+ * @param createdAt - Timestamp when the job was created
116
+ * @param now - Optional current timestamp (defaults to Date.now())
117
+ * @returns Object containing the effective priority and the calculated aging bonus
118
+ */
119
+ static calculateEffectivePriority(basePriority: number, createdAt: number, now?: number): {
120
+ effectivePriority: number;
121
+ agingBonus: number;
122
+ };
123
+ /**
124
+ * Convert system priority (1-20) to BullMQ priority (1-2097152).
125
+ *
126
+ * BullMQ uses lower numbers for higher priority. The mapping:
127
+ * - System 1 (highest) → BullMQ 1
128
+ * - System 10 → BullMQ ~1104750
129
+ * - System 20 (lowest) → BullMQ 2097152
130
+ *
131
+ * @param systemPriority - Priority in system format (1-20)
132
+ * @returns Priority in BullMQ format (1-2097152)
133
+ */
134
+ static toBullMQPriority(systemPriority: number): number;
135
+ /**
136
+ * Convert BullMQ priority (1-2097152) back to system priority (1-20).
137
+ *
138
+ * @param bullmqPriority - Priority in BullMQ format
139
+ * @returns Priority in system format (1-20)
140
+ */
141
+ static fromBullMQPriority(bullmqPriority: number): number;
142
+ /**
143
+ * Prepare job data with aging tracking metadata.
144
+ *
145
+ * This should be called when creating a new job to ensure aging metadata
146
+ * is properly attached to the job data.
147
+ *
148
+ * @param payload - The job payload/data
149
+ * @param priority - The original priority (1-20)
150
+ * @returns Object containing the payload and aging metadata
151
+ */
152
+ static prepareJobData(payload: unknown, priority: number): {
153
+ name?: string;
154
+ payload: unknown;
155
+ __aging__: AgingJobData;
156
+ };
157
+ /**
158
+ * Extract aging metadata from BullMQ job data.
159
+ *
160
+ * @param jobData - The job data from BullMQ
161
+ * @returns The aging data if present, null otherwise
162
+ */
163
+ static extractAgingData(jobData: unknown): AgingJobData | null;
164
+ /**
165
+ * Perform the actual aging check on waiting jobs.
166
+ *
167
+ * This is the internal implementation that scans waiting jobs and applies
168
+ * priority updates based on their wait time.
169
+ */
170
+ private performAgingCheck;
171
+ }
172
+ export default BullMQPriorityAgingService;
173
+ //# sourceMappingURL=bullmq-priority-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bullmq-priority-service.d.ts","sourceRoot":"","sources":["../../src/jobs/bullmq-priority-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,SAAS,CAAC;AAG5B;;;GAGG;AACH,MAAM,WAAW,YAAY;IACzB,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,UAAU,2BAA2B;IACjC,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAWD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,0BAA0B;IACnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkB;IACpD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAK;IACrC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAS;IACnD,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAO;IAElD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAA+B;IAEpD;;;;;;OAMG;gBACS,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,2BAA2B;IAgBvF;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmE5B;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA2C3B;;;;OAIG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;;;;OAOG;IACG,UAAU,IAAI,OAAO,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;KAC7B,CAAC;IAQF;;;;;;;;;;OAUG;IACH,MAAM,CAAC,0BAA0B,CAC7B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,GACb;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAcpD;;;;;;;;;;OAUG;IACH,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM;IAMvD;;;;;OAKG;IACH,MAAM,CAAC,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM;IAKzD;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAc,CACjB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,GACjB;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,YAAY,CAAA;KAAE;IAe/D;;;;;OAKG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI;IAiB9D;;;;;OAKG;YACW,iBAAiB;CAqHlC;AAED,eAAe,0BAA0B,CAAC"}