stacks-jobs

$npx mdskill add stacksjs/stacks/stacks-jobs

Creates and configures background job classes in app/Jobs/

  • Defines job structure with handle method and configuration options.
  • Depends on @stacksjs/queue and config/queue.ts for setup.
  • Uses job config like queue, tries, backoff, timeout, and rate.
  • Supports dispatching patterns: dispatch, dispatchIf, dispatchAfter, dispatchNow.

SKILL.md

.github/skills/stacks-jobsView on GitHub ↗
---
name: stacks-jobs
description: Use when creating background job classes in app/Jobs/ — job structure, the handle method, job configuration (queue, tries, backoff, timeout, rate), dispatching patterns (dispatch, dispatchIf, dispatchAfter, dispatchNow), or the Every schedule constants. For the queue system internals (workers, batching, events, drivers, testing), see stacks-queue.
license: MIT
compatibility: Bun >= 1.3.0, TypeScript
allowed-tools: Read Edit Write Bash Grep Glob
---

# Stacks Jobs

Background job classes defined in `app/Jobs/`.

## Key Paths
- Application jobs: `app/Jobs/`
- Queue config: `config/queue.ts`

## Creating a Job

```typescript
// app/Jobs/SendWelcomeEmail.ts
import { Job } from '@stacksjs/queue'

export default new Job({
  name: 'SendWelcomeEmail',
  description: 'Send welcome email to new user',
  queue: 'emails',       // queue name (default: 'default')
  tries: 3,              // max attempts
  backoff: 10,           // seconds between retries
  timeout: 30,           // max execution time (seconds)
  enabled: true,         // can be disabled

  async handle(payload: { email: string; name: string }) {
    console.log(`Sending to ${payload.email}`)
    // Do work here
    return { sent: true }
  }
})
```

## Job Configuration Options

```typescript
{
  name: string               // job identifier
  description?: string       // human-readable description
  queue?: string             // queue name (default: 'default')
  tries?: number             // max retry attempts
  backoff?: number           // seconds between retries
  backoffConfig?: {          // advanced backoff
    strategy: 'fixed' | 'exponential' | 'linear'
    initialDelay: number
    factor: number
    maxDelay: number
    jitter?: { enabled: boolean, factor: number }
  }
  timeout?: number           // max seconds per attempt
  rate?: string              // cron schedule (e.g., Every.Hour)
  enabled?: boolean          // enable/disable job
  handle: (payload?) => any  // job logic
}
```

## Dispatching Jobs

```typescript
// Simple dispatch
await SendWelcomeEmail.dispatch({ email: '[email protected]', name: 'John' })

// Conditional dispatch
await SendWelcomeEmail.dispatchIf(isNewUser, { email, name })
await SendWelcomeEmail.dispatchUnless(isExistingUser, { email, name })

// Delayed dispatch (60 second delay)
await SendWelcomeEmail.dispatchAfter(60, { email, name })

// Immediate execution (bypasses queue)
await SendWelcomeEmail.dispatchNow({ email, name })
```

## Fluent Job Builder

```typescript
import { job } from '@stacksjs/queue'

await job('SendWelcomeEmail', { email, name })
  .onQueue('emails')
  .delay(60)
  .tries(5)
  .timeout(30)
  .backoff([10, 30, 60])
  .dispatch()
```

## Scheduled Jobs

Use the `rate` property for automatic scheduling:

```typescript
import { Every } from '@stacksjs/enums'

export default new Job({
  name: 'CleanupExpiredTokens',
  rate: Every.Hour,          // runs every hour
  // rate: Every.Day,        // runs daily
  // rate: '*/5 * * * *',   // custom cron: every 5 minutes

  handle() {
    // cleanup logic
  }
})
```

Register in `app/Scheduler.ts`:
```typescript
import { schedule } from '@stacksjs/scheduler'

export default function() {
  schedule.job('CleanupExpiredTokens').hourly().setTimeZone('America/New_York')
}
```

## CLI Commands
```bash
buddy make:job [name]       # scaffold a new job
buddy queue                  # queue management
```

## Gotchas
- Jobs must export `default new Job({...})` — not a plain object
- The `handle()` method receives the payload passed to `dispatch()`
- `dispatchNow()` runs immediately in the current process — no queue involved
- Default queue driver is `sync` — jobs run immediately unless changed to `database` or `redis`
- Jobs with `rate` are auto-discovered by the scheduler
- Backoff array `[10, 30, 60]` means: retry after 10s, then 30s, then 60s
- Jobs should be idempotent — safe to retry on failure
- For queue workers, batching, events, and testing, see the `stacks-queue` skill

More from stacksjs/stacks

SkillDescription
stacks-actionsUse when working with Stacks server actions — creating actions in app/Actions/, auto-generated API actions from the useApi model trait, the 80+ default framework actions (auth, dashboard, commerce, content, deployment, jobs), action request/response handling, or action registration. Covers @stacksjs/actions and storage/framework/defaults/actions/.
stacks-aiUse when integrating AI capabilities into a Stacks application — using Anthropic/OpenAI/Ollama/AWS Bedrock drivers, image generation (DALL-E), vision analysis, RAG/vector search, embeddings, MCP (Model Context Protocol) clients, text summarization, sentiment analysis, content classification, personalization, or the buddy AI assistant. Covers @stacksjs/ai and config/ai.ts.
stacks-aliasUse when working with path aliases in a Stacks project — import resolution, module aliasing, or debugging import paths. Covers @stacksjs/alias which defines 260+ path mappings for the entire framework.
stacks-analyticsUse when adding analytics to a Stacks application — configuring Fathom or self-hosted analytics, generating tracking scripts, privacy-friendly analytics setup, or the analytics configuration. Covers @stacksjs/analytics and config/analytics.ts.
stacks-apiUse when building, modifying, or debugging API endpoints in a Stacks application — defining routes, handling requests, API middleware, working with the API server, HTTP client (fetcher), API resources, or OpenAPI generation. Covers both @stacksjs/api utilities and the stacks-api server implementation.
stacks-arraysUse when working with array utilities in Stacks — statistical operations (average, median, mode, standard deviation, z-score, percentile, covariance), array manipulation (unique, flatten, partition, shuffle, sample, move), containment checks, or the Arr facade. Covers @stacksjs/arrays.
stacks-authUse when implementing authentication, authorization, passkeys, TOTP/2FA, RBAC, gates, policies, session auth, token management, email verification, password resets, or rate limiting in a Stacks application. Covers the @stacksjs/auth package, config/auth.ts, app/Gates.ts, and app/Middleware/.
stacks-auto-importsUse when working with the Stacks auto-import system — understanding how browser and server auto-imports work, configuring auto-imported functions/models/composables, the auto-import manifests, type generation, or how globals are injected. Covers the auto-import pipeline at storage/framework/auto-imports/.
stacks-brandkitUse when defining or exploring a brand identity for a Stacks project and you want premium brand-kit REFERENCE IMAGES first - logo directions, palettes, typography specimens, identity boards, and application/mockup decks. Generates IMAGES ONLY, never code. Trained for minimalist, cinematic, editorial, dark-tech, luxury, cultural, security, gaming, developer-tool, and consumer-app brand systems with intentional logo concepting, sparse type, strong symbolic meaning, and disciplined palettes a coding step can build against.
stacks-browseUse for headless browser QA on Stacks applications — navigation, screenshots, responsive testing, console/network monitoring, and accessibility snapshots. Dependency-free: drives a system browser over the Chrome DevTools Protocol using only Bun (no Playwright/Puppeteer). Invoke with /stacks-browse.