All skills

Background job scheduling with sails-hook-quest for Sails.js applications. Use this skill when creating, scheduling, or managing background jobs, cron tasks, recurring scripts, or any deferred/periodic work in a Sails.js application.

Use this Skill: https://skilld.dev/gh/sailscastshq/boring-stack/quest

This session only. Nothing lands on disk.

rulesgetting-started.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Getting Started with Quest

What is Quest?

Quest is a job scheduling hook for Sails.js that transforms scripts in your scripts/ directory into scheduled background jobs. It provides:

  • Process isolation — each job runs as a separate child process via sails run
  • Multiple scheduling formats — cron expressions, human-readable intervals, shorthand notation, and later.js text
  • Full Sails context — jobs have access to models, helpers, and configuration
  • Overlap prevention — prevents the same job from running concurrently
  • Runtime control — start, stop, pause, resume, and run jobs programmatically

Installation

npm install sails-hook-quest

Quest auto-registers as a Sails hook — no manual wiring needed. It loads after the ORM is ready, so your jobs can safely use models.

Project Structure

my-app/
├── scripts/                  # Job scripts live here
│   ├── cleanup-sessions.js
│   ├── send-weekly-report.js
│   └── process-email-queue.js
├── config/
│   ├── quest.js              # Quest configuration
│   └── env/
│       └── console.js        # Lightweight environment for jobs
└── ...

Quick Start

1. Create a Job Script

Jobs are standard Sails scripts (the machine format used by sails run) with an added quest property that defines the schedule:

// scripts/cleanup-sessions.js
module.exports = {
  friendlyName: 'Cleanup sessions',

  description: 'Remove expired sessions older than 30 days.',

  quest: {
    interval: '1 hour'
  },

  inputs: {
    daysOld: {
      type: 'number',
      defaultsTo: 30
    }
  },

  fn: async function (inputs) {
    const cutoff = Date.now() - inputs.daysOld * 24 * 60 * 60 * 1000
    const deleted = await Session.destroy({
      lastActive: { '<': cutoff }
    }).fetch()

    sails.log.info(`Cleaned up ${deleted.length} expired sessions`)
  }
}

2. Configure Quest (Optional)

The defaults work out of the box, but you can customize behavior:

// config/quest.js
module.exports.quest = {
  // Auto-start scheduled jobs when Sails lifts (default: true)
  autoStart: true,

  // Default timezone for cron expressions (default: 'UTC')
  timezone: 'UTC',

  // Prevent overlapping runs by default (default: true)
  withoutOverlapping: true,

  // Environment for child processes (default: 'console')
  environment: 'console',

  // Directory containing job scripts (default: 'scripts')
  scriptsDir: 'scripts',

  // Path to sails executable (default: './node_modules/.bin/sails')
  sailsPath: './node_modules/.bin/sails',

  // Jobs can also be defined here instead of (or in addition to) script files
  jobs: []
}

3. Set Up the Console Environment

Jobs run in the console environment by default. Create a lightweight config that disables unnecessary hooks for faster job startup:

// config/env/console.js
module.exports = {
  hooks: {
    views: false,
    sockets: false,
    pubsub: false
  }
}

This significantly reduces startup time for job processes since they don't need view rendering, WebSockets, or pub/sub.

4. Lift Sails

sails lift

Quest automatically discovers scripts with a quest property, parses their schedules, and begins execution. You'll see log output like:

verbose: Registered job: cleanup-sessions { interval: '1 hour' }
verbose: Quest: Starting all jobs...

How It Works

  1. Discovery — on lift, Quest scans the scripts/ directory for files with a quest property
  2. Registration — jobs from both scripts and config/quest.js are merged into a registry
  3. Scheduling — the scheduler parses each job's timing (cron, interval, timeout, or date) and sets timers
  4. Execution — when a timer fires, the hook spawns sails run <script-name> as a child process
  5. Isolation — the child process lifts a separate Sails instance (in the console environment), runs the script's fn(), and exits
  6. Events — the parent process emits lifecycle events (quest:job:start, quest:job:complete, quest:job:error)
  7. Rescheduling — for recurring jobs (interval/cron), the next run is scheduled after the current one completes

Running Jobs Manually

You can always run any script manually, just like any Sails script:

sails run cleanup-sessions

Or with inputs:

sails run cleanup-sessions --daysOld=7

This is useful for testing jobs before setting up a schedule.

Default Configuration Reference

Option Default Description
autoStart true Auto-start all jobs when Sails lifts
timezone 'UTC' Default timezone for cron expressions
withoutOverlapping true Prevent concurrent runs of the same job
environment 'console' NODE_ENV for child processes
scriptsDir 'scripts' Directory to scan for job scripts
sailsPath './node_modules/.bin/sails' Path to the Sails CLI executable
jobs [] Config-defined jobs (merged with script jobs)

Source: SKILL.md on GitHub

1 warning17d4 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill provides a comprehensive framework for scheduling and managing background jobs in Sails.js applications using the sails-hook-quest library. It follows standard Sails.js development patterns, utilizing isolated child processes for task execution and providing a structured API for job lifecycle management. No malicious behaviors, obfuscation, or unauthorized data access patterns were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    6/8 files flagged

Signed by skilld at bf19e10. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 days ago.

Activeupdated 8 months ago
Other metadata
metadata
{
  "author": "sailscastshq",
  "version": "1.0.0",
  "tags": "quest, jobs, scheduling, cron, background, scripts, sails"
}

README badge

README badge for sailscastshq/boring-stack/quest