Schedulers
See how to create and configure your CRON job schedulers.
Introductionβ
Athenna's scheduler offers a fresh approach to managing scheduled tasks on your server. The scheduler allows you to fluently and expressively define your scheduler within your Athenna application itself. When using the scheduler, only a single cron entry is needed on your server. Your task schedule can be defined in your application's
Path.routes('cron.ts')
./src/routes/cron.ts
Path.cron('schedulers/MyScheduler.ts')
./src/cron/schedulers/MyScheduler.ts
Defining Schedulersβ
Schedulers are typically stored in the src/cron/scheduelrs
directory; however, you are free to choose your own storage
location as long as your schedulers can be imported and registered.
To create a new scheduler, you may use the make:scheduler
Artisan command. This command will create a new command class
in the src/cron/schedulers
directory and register it inside
schedulers
array of .athennarc.json
file. Don't worry if
this directory does not exist in your applicationβit will be
created the first time you run the make:scheduler
Artisan command:
node artisan make:scheduler DeleteRecentUsers
This will create the schedulers file and automatically register it for you:
{
"schedulers": [
"#src/cron/schedulers/DeleteRecentUsers" π
]
}
Defining schedulers logicβ
In this example, we will schedule a handler
method to be called
every day at midnight. Within the method we will execute a
database query to clear a table:
import { Database } from '@athenna/database'
import { Scheduler, type Context } from '@athenna/cron'
@Scheduler({ pattern: '0 0 * * *' })
export class DeleteRecentUsers {
public async handler(ctx: Context) {
await Database.table('recent_users').delete()
}
}
You can use Crontab.guru to help you create your CRON pattern, or simply ask ChatGPT π€©.
Defining schedulers in route fileβ
If you prefer, you can use the
Path.routes('cron.ts')
./src/routes/cron.ts
import { Cron } from '@athenna/cron'
import { Database } from '@athenna/database'
Cron.schedule().name('delete_recent_users')
.pattern('0 0 * * *')
.handler(async (ctx) => {
await Database.table('recent_users').delete()
})
Listing schedulers (Coming Soon)β
If you would like to view an overview of your scheduled tasks and the next time they are scheduled to run, you may use the cron:list Artisan command:
node artisan cron:list
Running scheduler locally (Coming Soon)β
When developing or even in production you might need to
force the scheduler to run. To do so you can use the
node artisan cron:run
command:
node artisan cron:run DeleteRecentUsers
You can also use a CRON pattern, this will trigger all the schedulers registered with the same pattern:
node artisan cron:run "0 0 * * *"
Using runOnInit
optionβ
Another way to run your schedulers locally is to define the
runOnInit=true
option:
import { Database } from '@athenna/database'
import { Scheduler, type Context } from '@athenna/cron'
@Scheduler({
runOnInit: true, π
pattern: '0 0 * * *'
})
export class DeleteRecentUsers {
public async handler(ctx: Context) {
await Database.table('recent_users').delete()
}
}
If using routes you may call the runOnInit()
method:
import { Cron } from '@athenna/cron'
import { Database } from '@athenna/database'
Cron.schedule().name('delete_recent_users')
.runOnInit(true) π
.pattern('0 0 * * *')
.handler(async (ctx) => {
await Database.table('recent_users').delete()
})
If this option is set to true
, it will automatically run your
scheduler when bootstrapping your Athenna application.
Dependency injection in schedulersβ
When using schedulers classes you are able to use the @Inject()
annotation to inject dependencies from you application within your
scheduler class:
import { Inject } from '@athenna/ioc'
import { Scheduler, type Context } from '@athenna/cron'
import { RecentUserService } from '#src/services/RecentUserService'
@Scheduler({ pattern: '0 0 * * *' })
export class DeleteRecentUsers {
@Inject()
public recentUserService: RecentUserService
public async handler(ctx: Context) {
await this.recentUserService.deleteAll()
}
}
Automatic constructor injectionβ
You can also use the automatic constructor injection if
your don't want to use the @Inject()
annotation:
import { Scheduler, type Context } from '@athenna/cron'
import type { RecentUserService } from '#src/services/RecentUserService'
@Scheduler({ pattern: '0 0 * * *' })
export class DeleteRecentUsers {
public recentUserService: RecentUserService
public constructor(recentUserService: RecentUserService) {
this.recentUserService = recentUserService
}
public async handler(ctx: Context) {
await this.recentUserService.deleteAll()
}
}