> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LuaJob

> Job class for a scheduled function with a cron, one-time, or interval schedule, a timeout, and a retry policy

`LuaJob` defines a [job](/concepts/jobs): an `execute` function the platform runs on a schedule, outside any conversation. Register jobs on `LuaAgent.jobs`; `lua push job` uploads a version, `lua deploy job` makes it live, and `lua jobs activate` and `lua jobs deactivate` start and pause the schedule. For a job created at runtime from a tool, such as a reminder for one end user, use [`Jobs.create`](/reference/sdk/jobs) instead.

*Verified against lua-cli 3.33.0.*

```ts theme={null}
import { LuaJob } from 'lua-cli';
```

## Quick example

```ts src/jobs/DailyDigestJob.ts theme={null}
import { LuaJob, Data } from 'lua-cli';

export default new LuaJob({
  name: 'daily-digest',
  description: 'Count open tickets every morning and store the total',
  schedule: { type: 'cron', expression: '0 9 * * *', timezone: 'Europe/London' },
  timeout: 120,
  retry: { maxAttempts: 3, backoffSeconds: 60 },
  async execute(job) {
    const open = await Data.get('tickets', { status: { $eq: 'open' } }, 1, 1);
    return { jobName: job.name, openTickets: open.pagination.totalCount };
  },
});
```

Run it once locally, without waiting for the schedule.

```bash theme={null}
lua test job --name daily-digest
```

```text Output theme={null}
…
✅ Job execution successful!

Job returned: Object — fields: jobName, openTickets
Output:
{ jobName: 'daily-digest', openTickets: 0 }
✨ Job works locally. To test in production:
   Trigger now:   `lua jobs trigger --job-name daily-digest`
   Inspect logs:  `lua logs --type job --name daily-digest --limit 5`
```

## Constructor

```ts theme={null}
new LuaJob(config: LuaJobConfig)
```

<ParamField path="name" type="string" required>
  Server-side identifier, kebab-case. Also `--name` for `lua push job` and `lua test job`, and `--job-name` for `lua jobs`.
</ParamField>

<ParamField path="description" type="string" required>
  One or two sentences shown in listings.
</ParamField>

<ParamField path="schedule" type="JobSchedule" required>
  When the job runs; see [Schedules](#schedules). Write it as an object literal or a constant the compiler can evaluate.
</ParamField>

<ParamField path="execute" type="(job: JobInstance) => Promise<any>" required>
  The function the platform runs. Its return value is stored on the execution.
</ParamField>

<ParamField path="timeout" type="number" default="300">
  Maximum run time in seconds. An integer from 1 to 600.
</ParamField>

<ParamField path="retry" type="{ maxAttempts: number; backoffSeconds?: number }">
  Retry policy for a failed attempt; see [Execution](#execution). Without it a failed occurrence isn't retried.
</ParamField>

<ParamField path="metadata" type="Record<string, any>">
  Static data available inside `execute` as `job.metadata`. The place for an end user ID the job should act for.
</ParamField>

The constructor throws when:

* `name` is empty or blank: ``LuaJob requires a non-empty `name` (used as the server-side identifier).``
* `timeout` is not an integer: ``LuaJob `timeout` must be an integer number of seconds.``
* `timeout` is outside 1 to 600: ``LuaJob `timeout` must be between 1 and 600 seconds.``

`lua compile` fails with `Job must have an execute function`, `Job must have a schedule` when it can't evaluate the schedule, and `Invalid schedule type: <type>. Must be one of: cron, interval, once`.

## Schedules

`JobSchedule` is a union of three shapes.

| `type`       | Fields                                                | Example                                                                     |
| ------------ | ----------------------------------------------------- | --------------------------------------------------------------------------- |
| `'cron'`     | `expression`: five-field cron; `timezone?`: IANA name | `{ type: 'cron', expression: '0 9 * * 1-5', timezone: 'America/New_York' }` |
| `'once'`     | `executeAt`: `Date` or ISO 8601 string                | `{ type: 'once', executeAt: '2026-12-31T10:00:00Z' }`                       |
| `'interval'` | `seconds`: number                                     | `{ type: 'interval', seconds: 900 }`                                        |

## Execution

`execute` receives a `JobInstance` with `id`, `name`, `metadata`, `activeVersion`, and `data`, plus `updateMetadata()`, `delete()`, `trigger()`, `activate()`, and `deactivate()`; the members are listed on [Jobs](/reference/sdk/jobs). `job.user()` resolves to the user recorded on the job; for a declared `LuaJob` that is the developer whose push created it, not an end user, and it throws `User API not initialized` when the job has no recorded end user. To act for an end user, read an ID from `metadata` and call `User.get(userId)`.

Each scheduled occurrence runs at least once. When an attempt fails or times out and `retry` is set, the platform retries while `maxAttempts` allows: each retry waits a fixed `backoffSeconds` (60 when omitted or `0`), with no jitter, and the platform stops after 10 attempts whatever `maxAttempts` says. Retries of one occurrence never run concurrently.

<Info>
  Deployed runs only. `job.execution` is `undefined` in `lua test`; every deployed run sets it to `{ executionId, attempt, occurrenceId, scheduledTime? }`, which isn't on the `JobInstance` type yet, so read it through a widened type and key side effects on `occurrenceId`.
</Info>

```ts theme={null}
type JobExecutionMeta = { executionId: string; attempt: number; occurrenceId: string; scheduledTime?: string };

const execution = (job as typeof job & { execution?: JobExecutionMeta }).execution;
```

## Methods

Read-only getters that return what was passed to the constructor, and a way to run the handler in a test.

| Method                      | Returns                                                         |
| --------------------------- | --------------------------------------------------------------- |
| `getName()`                 | `string`                                                        |
| `getDescription()`          | `string`                                                        |
| `getSchedule()`             | `JobSchedule`                                                   |
| `getTimeout()`              | `number`, the resolved timeout in seconds                       |
| `getRetry()`                | `{ maxAttempts: number; backoffSeconds?: number } \| undefined` |
| `getMetadata()`             | `Record<string, any> \| undefined`                              |
| `execute(job: JobInstance)` | `Promise<any>`, the handler's return value                      |

## Types

`LuaJobConfig` and `JobSchedule` are exported types; `JobInstance` is an exported class.

```ts theme={null}
import type { LuaJobConfig, JobSchedule } from 'lua-cli';

const nightly: JobSchedule = { type: 'cron', expression: '0 2 * * *', timezone: 'UTC' };
```

## See also

* [Jobs](/reference/sdk/jobs)
* [About jobs](/concepts/jobs)
* [Schedule a job](/build/schedule-a-job)
* [lua jobs](/reference/cli/jobs)
* [lua test](/reference/cli/test)
