Lifecycle & shutdown
EddyqModule integrates with Nest's lifecycle hooks. You don't need to call start() or shutdown() manually.
Boot
When Nest boots:
- The DI container resolves the eddyq client and every
@InjectQueuehandle. forRootconfig is validated.eddyq_jobsschema is checked — if migrations are pending, boot fails with a clear message. Runnpx eddyq migrate runfirst.- Processors register with the engine and begin polling the queues derived from
registerQueue. - Schedules (from
forRoot.schedulesand anyregisterQueue({ schedules })) are reconciled.
Set autoStart: false on forRoot to skip step 4 — useful for API pods that only enqueue.
Shutdown
Enable shutdown hooks in your main.ts:
ts
async function bootstrap() {
const app = await NestFactory.create(AppModule)
app.enableShutdownHooks()
await app.listen(3000)
}
bootstrap()On SIGINT / SIGTERM:
- Nest's shutdown sequence fires.
EddyqModulecallseddyq.shutdown()withgracefulShutdownMs(default 30_000).- In-flight handlers receive
signal.abort()and have the grace window to unwind. - The DB pool closes.
Configuring grace
ts
EddyqModule.forRoot({
databaseUrl: process.env.DATABASE_URL!,
gracefulShutdownMs: 60_000, // give long-running jobs more time
})Shutdown mode
shutdownMode controls what happens to in-flight rows:
"drain"(default) — wait up togracefulShutdownMsfor handlers to finish. Best for routine deploys."force"— abort immediately and proactively reset in-flight rows (running→pending) so other pods pick them up without waiting for the heartbeat sweep. Use when SIGKILL is imminent."abandon"— drop the runtime without touching DB rows. The next pod's heartbeat sweep recovers them afterstaleAfter. Panic-exits only.
Health checks
Inject the raw client into a HealthIndicator:
ts
import { InjectEddyq, type Eddyq } from '@eddyq/nestjs'
@Injectable()
export class EddyqHealth extends HealthIndicator {
constructor(@InjectEddyq() private readonly eddyq: Eddyq) {
super()
}
async check(key: string): Promise<HealthIndicatorResult> {
const stats = await this.eddyq.stats()
return this.getStatus(key, stats.healthy)
}
}