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.

rulesscheduling.md

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

Scheduling Formats

Quest supports multiple scheduling formats through three parsing libraries: cron-parser, human-interval, and @breejs/later. Choose the format that best fits your use case.

Cron Expressions

Standard 5-field cron format. Best for time-of-day or calendar-based schedules.

// scripts/daily-backup.js
module.exports = {
  friendlyName: 'Daily backup',
  description: 'Back up the database every day at 2 AM.',

  quest: {
    cron: '0 2 * * *'
  },

  fn: async function () {
    await sails.helpers.backupDatabase()
  }
}

Common Cron Patterns

quest: {
  cron: '* * * * *'
} // Every minute
quest: {
  cron: '*/5 * * * *'
} // Every 5 minutes
quest: {
  cron: '0 * * * *'
} // Every hour (on the hour)
quest: {
  cron: '0 2 * * *'
} // Daily at 2:00 AM
quest: {
  cron: '0 9 * * MON'
} // Every Monday at 9:00 AM
quest: {
  cron: '0 0 1 * *'
} // First day of every month at midnight
quest: {
  cron: '0 0 * * MON-FRI'
} // Weekdays at midnight
quest: {
  cron: '0 */6 * * *'
} // Every 6 hours
quest: {
  cron: '30 4 * * SUN'
} // Every Sunday at 4:30 AM

Cron Field Reference

┌──────── minute (0–59)
│ ┌────── hour (0–23)
│ │ ┌──── day of month (1–31)
│ │ │ ┌── month (1–12 or JAN–DEC)
│ │ │ │ ┌ day of week (0–7 or SUN–SAT, 0 and 7 are Sunday)
│ │ │ │ │
* * * * *

Cron Options

Pass custom options to cron-parser via cronOptions:

quest: {
  cron: '0 9 * * *',
  cronOptions: {
    startDate: new Date('2025-01-01'),
    endDate: new Date('2025-12-31')
  }
}

Human-Readable Intervals

Natural language intervals parsed by the human-interval library. Best for simple recurring intervals.

// scripts/health-check.js
module.exports = {
  friendlyName: 'Health check',
  description: 'Ping external APIs every 5 minutes.',

  quest: {
    interval: '5 minutes'
  },

  fn: async function () {
    const status = await sails.helpers.checkApiHealth()
    if (!status.healthy) {
      await sails.helpers.sendSlackAlert.with({
        message: `API unhealthy: ${status.error}`
      })
    }
  }
}

Supported Interval Formats

// Seconds
quest: {
  interval: '30 seconds'
}

// Minutes
quest: {
  interval: '5 minutes'
}
quest: {
  interval: '1 minute'
}

// Hours
quest: {
  interval: '2 hours'
}
quest: {
  interval: '1 hour'
}

// Days
quest: {
  interval: '7 days'
}
quest: {
  interval: '1 day'
}

// "every" prefix also works
quest: {
  interval: 'every 5 minutes'
}
quest: {
  interval: 'every 2 hours'
}

Shorthand Notation

Compact format for quick interval definitions. The shorthand is converted internally to the full human-readable format.

quest: {
  interval: '5s'
} // → '5 seconds'
quest: {
  interval: '10m'
} // → '10 minutes'
quest: {
  interval: '2h'
} // → '2 hours'
quest: {
  interval: '1d'
} // → '1 day'
quest: {
  interval: '30s'
} // → '30 seconds'

Shorthand Reference

Suffix Expands To Example
s seconds 30s → 30 seconds
m minutes 5m → 5 minutes
h hours 2h → 2 hours
d days 1d → 1 day

Numeric Intervals (Milliseconds)

Pass a number to set the interval in milliseconds:

quest: {
  interval: 300000
} // Every 5 minutes (300,000 ms)
quest: {
  interval: 60000
} // Every 1 minute
quest: {
  interval: 3600000
} // Every 1 hour

Later.js Text Expressions

For complex calendar-based schedules, use text expressions parsed by @breejs/later:

quest: {
  interval: 'at 10:00 am'
}
quest: {
  interval: 'at 3:30 pm'
}
quest: {
  interval: 'at 10:00 am on the 1st'
}
quest: {
  interval: 'at 10:00 am on the 15th'
}

These expressions support the full later.parse.text() syntax.

One-Time Execution

Timeout (Delayed One-Time Run)

Run a job once after a specified delay from when Sails lifts:

// scripts/warmup-cache.js
module.exports = {
  friendlyName: 'Warmup cache',
  description: 'Pre-compute expensive queries after startup.',

  quest: {
    timeout: '10 minutes'
  },

  fn: async function () {
    await sails.helpers.warmupDashboardCache()
  }
}

Timeout accepts all the same formats as interval:

quest: {
  timeout: '30 seconds'
} // Human-readable
quest: {
  timeout: '5m'
} // Shorthand
quest: {
  timeout: 60000
} // Milliseconds
quest: {
  timeout: 'at 3:00 pm'
} // Later.js (next occurrence)

Specific Date

Run a job once at an exact date and time:

// scripts/launch-campaign.js
module.exports = {
  friendlyName: 'Launch campaign',
  description: 'Start the marketing campaign at a specific time.',

  quest: {
    date: new Date('2025-03-15T09:00:00Z')
  },

  fn: async function () {
    await sails.helpers.activateCampaign()
    await sails.helpers.sendNotification.with({
      message: 'Campaign is now live!'
    })
  }
}

Note: date and timeout cannot be combined — use one or the other. If the date is in the past, the job will not run.

Timezone Configuration

Global Timezone

Set the default timezone for all cron jobs in config/quest.js:

// config/quest.js
module.exports.quest = {
  timezone: 'America/New_York'
}

Per-Job Timezone Override

Override the global timezone for a specific job:

// scripts/eu-report.js
module.exports = {
  friendlyName: 'EU daily report',

  quest: {
    cron: '0 9 * * *',
    timezone: 'Europe/London' // Run at 9 AM London time
  },

  fn: async function () {
    // ...
  }
}

The timezone primarily affects cron expressions. Interval-based schedules (like '5 minutes') are timezone-agnostic since they're relative delays.

Decision Guide

Use Case Format Example
Run at specific times of day Cron cron: '0 9 * * *'
Run on specific days Cron cron: '0 0 * * MON'
Run every N minutes/hours Interval interval: '5 minutes'
Quick prototyping Shorthand interval: '30s'
Complex calendar rules Later.js interval: 'at 10:00 am on the 1st'
Run once after delay Timeout timeout: '10 minutes'
Run at exact date Date date: new Date('2025-03-15')
Need timezone control Cron + timezone cron: '0 9 * * *', timezone: 'US/Eastern'

Long Delays

JavaScript's setTimeout has a maximum safe delay of ~24.8 days (2,147,483,647 ms). Quest handles this automatically — for schedules beyond this limit, it sets intermediate timers that recalculate and reschedule as the target time approaches. You don't need to worry about this.

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