Skip to content

feat(agenda): migrate @tsed/agenda to Agenda v6 #3375

Description

@Romakita

Is your feature request related to a problem? Please describe.

@tsed/agenda is still wired against Agenda v5 APIs and configuration, while Agenda v6 introduces breaking changes in backend wiring, define() signature, and job querying.

Today the package is coupled to v5 in several places:

  • runtime instantiation still forwards Ts.ED config directly to new Agenda(opts) in packages/third-parties/agenda/src/services/AgendaService.ts:109
  • job definitions still use the old agenda.define(name, options, processor) order in packages/third-parties/agenda/src/services/AgendaService.ts:14
  • public config typing still aliases AgendaConfig directly in packages/third-parties/agenda/src/interfaces/interfaces.ts:1
  • integration tests still bootstrap Agenda with agenda.db and assert via agenda.jobs() in packages/third-parties/agenda/test/agenda-define.integration.spec.ts:26
  • package docs still document the v5 db configuration shape in packages/third-parties/agenda/readme.md:60

Agenda v6 migration guide also changes the storage model:

  • MongoDB backend moves to @agendajs/mongo-backend
  • backend is now required instead of passing db / mongo / repository directly to Agenda
  • ensureIndex and sort move to MongoBackend
  • agenda.define() becomes define(name, processor, options)
  • agenda.jobs() is replaced by agenda.queryJobs()

Reference:

Describe the solution you'd like

Migrate @tsed/agenda to Agenda v6 with a hard cut to the v6 configuration model and explicit migration notes for users.

Proposed scope

  1. Upgrade package dependencies

    • bump agenda from ^5.0.0 to ^6
    • add @agendajs/mongo-backend
    • tighten peerDependencies to reflect the supported Agenda major version
  2. Refactor Ts.ED config mapping

    • stop passing Ts.ED agenda config directly to new Agenda(...)
    • build a v6 backend instance explicitly before creating Agenda
    • keep Ts.ED lifecycle flags (enabled, disableJobProcessing, drainJobsBeforeClose) outside of Agenda backend config
  3. Switch Ts.ED config to the v6 backend model

    • do not support legacy db / mongo / repository top-level config in @tsed/agenda
    • require backend explicitly in the Ts.ED agenda configuration
    • move ensureIndex and sort into backend construction
    • document this as a package-level breaking change for @tsed/agenda
  4. Update internal Agenda API usage

    • change agenda.define(jobName, options, jobProcessor) to agenda.define(jobName, jobProcessor, options)
    • audit any helper/proxy method that wraps define() so the DI context wrapper still works
  5. Update tests and examples

    • replace agenda.jobs() assertions with agenda.queryJobs()
    • update test bootstrap to use backend
    • remove assertions tied to internal v5-only fields when needed
    • refresh packages/third-parties/agenda/readme.md examples and Agendash snippet
    • update docs/tutorials/agenda.md
    • add migration notes in both docs entry points
    • validate agendash integration against Agenda v6 and update related examples

Technical design notes

A. Config normalization layer

Refactor AgendaSettings so that Ts.ED only passes valid v6 configuration to Agenda.

  • input: AgendaSettings
  • output:
    • v6 Agenda options with an explicit backend
    • preserved Ts.ED-only flags

Suggested shape:

type AgendaSettings = {
  enabled?: boolean;
  disableJobProcessing?: boolean;
  drainJobsBeforeClose?: boolean;
  backend?: AgendaBackend;
} & AgendaConfig;

Validation / migration rules:

  • backend becomes mandatory when agenda.enabled === true
  • legacy top-level config (db, mongo, repository, ensureIndex, sort) is removed from Ts.ED docs and examples
  • sort examples use v6 string directions ("asc" / "desc")

B. Hard-cut configuration diff

Current Ts.ED configuration:

agenda: {
  enabled: true,
  db: {
    address: mongoConnectionString
  }
}

New required Ts.ED configuration:

agenda: {
  enabled: true,
  backend: new MongoBackend({
    address: mongoConnectionString
  })
}

Migration diff:

 import {Configuration} from "@tsed/di";
 import "@tsed/agenda";
+import {MongoBackend} from "@agendajs/mongo-backend";
 
 const mongoConnectionString = "mongodb://127.0.0.1/agenda";
 
 @Configuration({
   agenda: {
     enabled: true,
-    db: {
-      address: mongoConnectionString
-    }
+    backend: new MongoBackend({
+      address: mongoConnectionString
+    })
   }
 })
 export class Server {}

Advanced migration diff:

 agenda: {
   enabled: true,
-  mongo: db,
-  ensureIndex: true,
-  sort: {
-    nextRunAt: 1,
-    priority: -1
-  },
+  backend: new MongoBackend({
+    mongo: db,
+    ensureIndex: true,
+    sort: {
+      nextRunAt: "asc",
+      priority: "desc"
+    }
+  }),
   processEvery: "30 seconds",
   maxConcurrency: 20
 }

C. Query API migration

Agenda v6 replaces:

await agenda.jobs(query)

with:

const {jobs} = await agenda.queryJobs({...})

This impacts:

  • integration tests
  • any internal helper code added in the future around job lookup
  • documentation snippets that suggest using agenda.jobs()

D. agendash impact

There is also an explicit impact on agendash integration and documentation.

Upstream agenda/agendash now documents an ESM-only middleware API built around named exports such as expressMiddleware, together with Agenda v6 + MongoBackend.

Current Ts.ED docs still show an outdated pattern based on:

  • require("agendash")
  • Agendash(agenda)
  • pre-v6 Agenda construction examples

This must be updated to the upstream package API.

Required documentation diff:

 import {AfterRoutesInit, PlatformApplication} from "@tsed/platform-http";
 import {Inject, Configuration, Module} from "@tsed/di";
 import {Agenda} from "agenda";
-const Agendash = require("agendash");
+import {expressMiddleware} from "agendash";
 
 @Module()
 export class AgendashModule implements AfterRoutesInit {
   @Configuration()
   config: Configuration;
 
   @Inject()
   agenda: Agenda;
 
   @Inject()
   app: PlatformApplication;
 
   $afterRoutesInit() {
     if (this.config.agenda?.enabled) {
-      this.app.use("/agendash", Agendash(this.agenda));
+      this.app.use("/agendash", expressMiddleware(this.agenda));
     }
   }
 }

Installation diff to document:

 npm install --save @tsed/agenda
-npm install --save agenda
+npm install --save agenda @agendajs/mongo-backend agendash

Acceptance for this part:

  • Ts.ED docs use the upstream agendash middleware API (expressMiddleware for Express)
  • Ts.ED docs show Agenda v6 + MongoBackend in agendash examples
  • Ts.ED docs mention that agendash is also ESM-based and aligned with the Node 18+ Agenda v6 stack

E. Public API / typing impact

TypeScript typings will change:

  • AgendaSettings must expose backend as the v6 integration point
  • Mongo-specific constructor options must no longer exist at top-level in Ts.ED config types
  • if custom repositories remain supported, they must be supplied through a custom AgendaBackend, not through the removed v5 top-level repository shortcut

Describe alternatives you've considered

  1. Hard cut to pure Agenda v6 API

    • Pros: simpler implementation, deterministic runtime behavior, types aligned with upstream, no ambiguous config handling
    • Cons: package-level breaking change for existing @tsed/agenda users
  2. Keep dual config support

    • Pros: smaller migration surface for existing users
    • Cons: rejected; @tsed/agenda cannot reliably and cleanly support both the legacy v5-style config and the v6 backend model from its side

Recommended path: hard cut to v6 for @tsed/agenda.

Additional context

Release policy / breaking-change note

This migration can be treated as a breaking change for the @tsed/agenda package itself without implying a breaking change for the Ts.ED core framework.

Proposed release note wording:

  • @tsed/agenda uses Agenda v6 starting from the Ts.ED version that ships this package update
  • migration impacts are limited to the @tsed/agenda integration surface
  • breaking changes in Ts.ED extensions/packages do not automatically imply a breaking change for Ts.ED core
  • @tsed/agenda no longer accepts the legacy top-level db / mongo / repository configuration shape

Documentation / migration notes

The migration work should include two explicit documentation updates:

  • packages/third-parties/agenda/readme.md
    • add a migration note that explains the switch to Agenda v6
    • show the new required backend-based configuration
    • include explicit before/after diffs for configuration changes
    • update the agendash example to the upstream middleware API (expressMiddleware)
  • docs/tutorials/agenda.md
    • update tutorial examples to Agenda v6
    • add a migration note for users upgrading existing projects
    • add an AI-facing migration note section with direct before/after snippets so coding agents can reliably rewrite old config and API usage
    • update the agendash section to the upstream middleware API and package install commands

Impact summary

  • Runtime: AgendaService factory must instantiate a backend explicitly before creating Agenda
  • Typing: AgendaSettings needs a v6-only type centered on backend
  • Tests: all integration tests using agenda.db, agenda.jobs(), and v5 internal fields must be updated
  • Docs: packages/third-parties/agenda/readme.md examples must switch to MongoBackend and remove legacy top-level config
  • Docs: docs/tutorials/agenda.md must be updated in parallel so package README and main tutorial do not diverge
  • Agendash: middleware usage and examples must be updated to the current upstream agenda/agendash API
  • Dependencies: package manifest and peer dependency contract must be reviewed

Suggested implementation checklist

  • bump agenda to v6 and add @agendajs/mongo-backend
  • remove legacy top-level config support from @tsed/agenda typings and docs
  • update AgendaService factory to require backend
  • swap define() call order in the DI wrapper and definition registration
  • migrate tests from jobs() to queryJobs()
  • add migration note to packages/third-parties/agenda/readme.md
  • update docs/tutorials/agenda.md
  • update agendash examples to expressMiddleware(this.agenda)
  • update install instructions to include @agendajs/mongo-backend and agendash
  • add AI-oriented migration note with before/after config and query examples
  • verify expressMiddleware(this.agenda) works with the injected Agenda v6 instance

Acceptance criteria

  • @tsed/agenda runs on Agenda v6
  • MongoDB usage works through @agendajs/mongo-backend
  • existing Ts.ED lifecycle hooks ($beforeAgendaStart, $afterAgendaStart, disableJobProcessing, drainJobsBeforeClose) still behave as before
  • decorator-based registration still works with the new define() signature
  • package tests pass after replacing v5 query/config APIs
  • packages/third-parties/agenda/readme.md clearly documents the supported v6 configuration shape with explicit migration diffs
  • docs/tutorials/agenda.md reflects the same migration guidance and includes upgrade notes usable by humans and AI agents
  • agendash usage is documented with the upstream middleware API and verified against the injected Agenda v6 instance

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions