See the best posts from any Bluesky account
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Wire firehose threshold scan into the queue worker's scheduler

Boot adonisjs-scheduler's Worker inside `node ace queue:work` so the
every-minute ThresholdScanJob dispatch runs in the same process as the
existing backfill worker. No dedicated scheduler container is needed and
the 6.9 GB memory budget is unchanged.

Also widen the start/scheduler.ts preload to include the `console`
environment so the schedule registrations load when queue:work boots.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+52 -3
+5 -1
adonisrc.ts
··· 91 91 () => import('#start/validator'), 92 92 { 93 93 file: () => import('#start/scheduler'), 94 - environment: ['web'], 94 + // The scheduler file defines recurring work dispatched inside the 95 + // queue-worker process via `node ace queue:work` (console env). The 96 + // `web` env entry is kept so `pnpm dev` boots it too for local dev, 97 + // although the scheduler Worker itself only starts inside queue:work. 98 + environment: ['console', 'web'], 95 99 }, 96 100 ], 97 101
+27
commands/queue_work.ts
··· 1 1 import QueueWorkBase from '@adonisjs/queue/commands/queue_work' 2 + import { Worker as SchedulerWorker } from 'adonisjs-scheduler' 2 3 3 4 /** 4 5 * Local shadow of @adonisjs/queue's queue:work command. ··· 9 10 * forces Node's default-action exit. We wait for super.run() to finish 10 11 * (boringnode's shutdown handler has already drained the pool by then), then 11 12 * terminate the app and exit explicitly. 13 + * 14 + * We also boot `adonisjs-scheduler`'s Worker inside this same process so the 15 + * scheduled `ThresholdScanJob` dispatches fire from the queue-worker container, 16 + * avoiding a dedicated scheduler entrypoint (see docs/superpowers/specs/ 17 + * 2026-04-14-firehose-virality-webhook-design.md §"Threshold poll"). 12 18 */ 13 19 export default class QueueWork extends QueueWorkBase { 20 + private schedulerWorker?: SchedulerWorker 21 + 14 22 async run() { 15 23 try { 24 + this.schedulerWorker = new SchedulerWorker(this.app) 25 + await this.schedulerWorker.start() 26 + } catch (error) { 27 + this.logger.error( 28 + `Scheduler worker failed to start: ${ 29 + error instanceof Error ? error.message : String(error) 30 + }` 31 + ) 32 + } 33 + 34 + try { 16 35 await super.run() 17 36 } catch (error) { 18 37 this.logger.error(error instanceof Error ? error.message : String(error)) 19 38 this.exitCode = 1 39 + } 40 + 41 + if (this.schedulerWorker) { 42 + try { 43 + await this.schedulerWorker.stop() 44 + } catch { 45 + /* ignore */ 46 + } 20 47 } 21 48 try { 22 49 await this.app.terminate()
+20 -2
start/scheduler.ts
··· 3 3 | Scheduler 4 4 |-------------------------------------------------------------------------- 5 5 | 6 - | This file is used to define scheduled jobs. You can schedule jobs to run 7 - | at specific intervals using cron expressions or duration strings. 6 + | Scheduled work dispatched by `adonisjs-scheduler`. The scheduler Worker is 7 + | booted inside `node ace queue:work` (see commands/queue_work.ts) so these 8 + | jobs run in the same container as the existing backfill worker. 8 9 | 9 10 */ 11 + 12 + import scheduler from 'adonisjs-scheduler/services/main' 13 + import ThresholdScanJob from '#jobs/threshold_scan_job' 14 + 15 + /** 16 + * Every 60 seconds, enqueue a ThresholdScanJob so the queue worker picks it 17 + * up and scans `like_counts_daily` for posts crossing the firehose virality 18 + * thresholds. `withoutOverlapping` avoids piling up duplicate schedulings if 19 + * the dispatch itself is slow. 20 + */ 21 + scheduler 22 + .call(async () => { 23 + await ThresholdScanJob.dispatch({}) 24 + }) 25 + .everyMinute() 26 + .withoutOverlapping() 27 + .tag('firehose-threshold-scan')