Introducing Quest - Elegant Job Scheduling for Sails.js
Kelvin Omereshone
@Dominus_Kelvin
I’m thrilled to announce Sails Quest, a job scheduling hook for Sails.js that makes running scheduled tasks feel natural and intuitive.
Why Quest?
If you’ve ever needed to run background jobs in a Sails application - sending scheduled emails, cleaning up old data, processing queues, or running periodic reports - you know the options have been limited. You either reach for external tools like cron jobs, or cobble together something with setInterval.
Quest changes that. It lets you schedule jobs using the same Sails scripts you already know and love, with human-readable scheduling syntax and full access to your Sails application context.
What Makes Quest Special
Human-Readable Scheduling
Forget cryptic cron expressions (though Quest supports those too). Schedule jobs the way you think about them:
quest: {
interval: 'every hour'
// or '30 seconds', '5 minutes', '2 days'
}
Full Sails Context
Your scheduled jobs have complete access to models, helpers, and configuration - exactly like your regular Sails scripts:
// scripts/cleanup-sessions.js
module.exports = {
friendlyName: 'Cleanup old sessions',
quest: {
interval: '1 hour',
withoutOverlapping: true
},
inputs: {
daysOld: {
type: 'number',
defaultsTo: 30
}
},
fn: async function(inputs) {
const deleted = await Session.destroy({
lastActive: { '<': new Date(Date.now() - inputs.daysOld * 24*60*60*1000) }
}).fetch()
await sails.helpers.sendEmail.with({
to: '[email protected]',
subject: 'Cleanup complete',
text: `Deleted ${deleted.length} sessions`
})
return { deletedCount: deleted.length }
}
}
Flexible Configuration
Define schedules in your scripts, in config, or both. Quest intelligently merges them with a clear priority system:
- Script’s
questconfig takes priority for scheduling - Config inputs serve as defaults that scripts can override
- Runtime inputs from
sails.quest.run()take highest priority
Built-in Safeguards
Quest prevents jobs from stepping on each other with withoutOverlapping, validates that scripts exist before running, and provides helpful error messages when something goes wrong.
Getting Started
Install Quest:
npm install sails-hook-quest
Create a scheduled job in scripts/:
// scripts/health-check.js
module.exports = {
friendlyName: 'Health check',
quest: {
interval: '5 minutes'
},
fn: async function() {
const status = await sails.helpers.checkHealth()
console.log('System healthy:', status)
return status
}
}
That’s it. When Sails lifts, Quest automatically discovers your jobs and starts scheduling them.
Runtime Control
Quest exposes a clean API for controlling jobs programmatically:
// Run a job immediately
await sails.quest.run('health-check')
// Run with custom inputs
await sails.quest.run('cleanup-sessions', { daysOld: 7 })
// Start/stop scheduling
sails.quest.start('weekly-report')
sails.quest.stop('weekly-report')
// Pause without removing schedule
sails.quest.pause('heavy-task')
sails.quest.resume('heavy-task')
Event System
Monitor your jobs with Quest’s event system:
// config/bootstrap.js
sails.on('quest:job:start', (data) => {
console.log(`Job ${data.name} started`)
})
sails.on('quest:job:complete', (data) => {
console.log(`Job ${data.name} completed in ${data.duration}ms`)
})
sails.on('quest:job:error', (data) => {
// Send alert to Slack, Discord, etc.
console.error(`Job ${data.name} failed:`, data.error)
})
Documentation
Check out the full documentation covering:
Try It Today
npm install sails-hook-quest
Report issues or contribute at on GitHub.
Happy scheduling!