Problem
When using Vapor Queues to schedule jobs, the typical API is:
app.queues
.schedule(MyJob()).hourly().at(0)
This schedules once per hour. If we want to run it every N minutes (e.g., every 5, 10, or 15), we have to manually register multiple .at(…) calls, which results in repetitive code, prone to errors (duplicated/forgotten minutes), and difficult to read.
Solution
We extract a helper over Application.Queues that registers the same ScheduledJob multiple times within the hour using a stride with step minutes. This way, with a single call we express: “run it every N minutes”.
extension Application.Queues {
func scheduleEvery(
_ job: ScheduledJob,
minutes: Int
) {
for minuteOffset in stride(
from: 0,
to: 60,
by: minutes
) {
schedule(job).hourly()
.at(.init(integerLiteral: minuteOffset))
}
}
}
Key points:
- Uses stride(from: 0, to: 60, by: minutes) to generate minute offsets within the hour.
- For each offset it registers hourly().at(…), avoiding logic duplication.
- If minutes doesn’t divide 60, the last execution will be the largest multiple < 60 (e.g., minutes = 7 ⇒ 0, 7, 14, …, 56).
Result
Usage example:
func configure(_ app: Application) throws {
app.queues.scheduleEvery(MyJob(), minutes: 5)
}
A concise and self-expressive API for short periodic tasks:
- Less boilerplate: a single call registers all triggers.
- Fewer errors: no manual lists of .at(…) or duplicated minutes.
- Readable and testable: the pattern is evident and easy to verify.
Keep coding, keep running 🏃♂️