Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision | |||
| iqxwebnext:technical:web_jobs [2026/10/05 18:23] – Gareth Johnstone | iqxwebnext:technical:web_jobs [2026/10/05 20:02] (current) – Gareth Johnstone | ||
|---|---|---|---|
| Line 34: | Line 34: | ||
| The rules that matter: | The rules that matter: | ||
| - | - **The return value is the result.** A plain value or object is sent as JSON; a `response.*` value is sent as that response. `finish ( result )` still works (jobs written before October 2026 use it) and whichever of the two happens first wins. | + | - **The return value is the result.** A plain value or object is sent as JSON; a `response.*` value is sent as that response. |
| - **An uncaught error fails the run immediately** with `JOB-001` and the message — including a rejected promise nobody caught and a throw inside a timer. You no longer need a `try/catch` just to make failures prompt; catch only where you want to turn an error into a particular answer. | - **An uncaught error fails the run immediately** with `JOB-001` and the message — including a rejected promise nobody caught and a throw inside a timer. You no longer need a `try/catch` just to make failures prompt; catch only where you want to turn an error into a particular answer. | ||
| - **`success: false` in a JSON result marks the run as failed.** The caller gets a `JOB-001` error *instead of* your payload, the run is counted as a failure, and a scheduled run is recorded as failed. Use it to mean "this did not work". For "no rows matched" | - **`success: false` in a JSON result marks the run as failed.** The caller gets a `JOB-001` error *instead of* your payload, the run is counted as a failure, and a scheduled run is recorded as failed. Use it to mean "this did not work". For "no rows matched" | ||
| Line 65: | Line 65: | ||
| | `request` | `{ method, url, path, query, headers, ip, caller }`. `method` tells a page job a landing `GET` from a submitted `POST`; a scheduled run sees `" | | `request` | `{ method, url, path, query, headers, ip, caller }`. `method` tells a page job a landing `GET` from a submitted `POST`; a scheduled run sees `" | ||
| | `userID`, `isAuthenticated` | The caller' | | `userID`, `isAuthenticated` | The caller' | ||
| - | | `db.exec ( sql, params? )` | Runs the SQL as the pears (business-table) user with `?` placeholders bound from the array, and resolves to an **array of row objects** for a `SELECT` (`{ affectedRows }` for insert/ | + | | `db.exec ( sql, params? )` | Runs the SQL as the pears (business-table) user with `?` placeholders bound from the array, and resolves to an **array of row objects** for a `SELECT` (`{ affectedRows }` for insert/ |
| | `http ( url, options? )` | Outbound HTTP. `options`: `method`, `headers`, `body` (a string, bytes, or an object which is sent as JSON), `username`/ | | `http ( url, options? )` | Outbound HTTP. `options`: `method`, `headers`, `body` (a string, bytes, or an object which is sent as JSON), `username`/ | ||
| | `require ( name )` | Loads an **approved** module synchronously: | | `require ( name )` | Loads an **approved** module synchronously: | ||
| | `console` | `log`/ | | `console` | `log`/ | ||
| - | | `response` | Builders for non-JSON answers — see *Responses*. `rawResponse ( body, headers )` is the older form of `response.raw`. | | + | | `response` | Builders for non-JSON answers — see *Responses*. | |
| | `sign ( payload, ttlSeconds? )`, `verify ( token )` | A signed, expiring token (HMAC, keyed from the server secret). `verify` returns the payload or `null`. This is how a multi-step page proves that an earlier step passed — see *Serving pages*. Default TTL 15 minutes. | | | `sign ( payload, ttlSeconds? )`, `verify ( token )` | A signed, expiring token (HMAC, keyed from the server secret). `verify` returns the payload or `null`. This is how a multi-step page proves that an earlier step passed — see *Serving pages*. Default TTL 15 minutes. | | ||
| | `breakpoint ( )` | Pauses the job when it is being run under the debugger; a no-op otherwise (so is a plain `debugger` statement). See *Debugging*. | | | `breakpoint ( )` | Pauses the job when it is being run under the debugger; a no-op otherwise (so is a plain `debugger` statement). See *Debugging*. | | ||
| | `limits` | The resolved `{ runtimeMs, memoryMb, cpuMs }` for this run. | | | `limits` | The resolved `{ runtimeMs, memoryMb, cpuMs }` for this run. | | ||
| | `Buffer`, `URL`, `URLSearchParams`, | | `Buffer`, `URL`, `URLSearchParams`, | ||
| - | | `extendLimits ( )` | Deprecated — declare limits in the header instead. Still extends the runtime for old jobs and logs a warning. | | ||
| ## Who may call a job | ## Who may call a job | ||
| Line 249: | Line 248: | ||
| | `JOB-002` | `require ( )` of a module that is not approved or not installed. | | | `JOB-002` | `require ( )` of a module that is not approved or not installed. | | ||
| | `JOB-003` | A limit was hit: runtime, memory or CPU. The message says which. | | | `JOB-003` | A limit was hit: runtime, memory or CPU. The message says which. | | ||
| - | | `JOB-004` | The job finished without a result (`finish ( )` with nothing, or nothing returned | + | | `JOB-004` | The job finished without a result (nothing |
| | `AUTH-SESSION-001`, | | `AUTH-SESSION-001`, | ||
| | `SYS-429` | Too many: the rate limit for callers without credentials, | | `SYS-429` | Too many: the rate limit for callers without credentials, | ||
| Line 257: | Line 256: | ||
| ## Trying it | ## Trying it | ||
| - | The repo ships a small test pack; run each and compare with its header. `_test-limits` returns the resolved limits, and `? | + | The repo ships a small test pack; run each and compare with its header. `_test-limits` returns the resolved limits, and `? |
| - | + | ||
| - | ## Jobs written before October 2026 | + | |
| - | + | ||
| - | The earlier engine ran the file as a synchronous function body, so every job wrapped itself in `(async function (params, userID, finish) { … })(params, userID, finish)` and used `await require ( )`, `getDB ( )` and `finish ( )`. All of that still works unchanged inside the new wrapper; the only behavioural differences are that an uncaught error now fails at once instead of waiting for the timeout, that `extendLimits ( )` logs a deprecation pointing at the header, and that files must be named `< | + | |
| ## For developers | ## For developers | ||