pipework 0.170.0 → 0.172.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/REFERENCE.md +37 -0
- package/dist/REFERENCE.md +195 -7
- package/dist/async/jobs/scheduler.d.ts +5 -0
- package/dist/async/jobs/scheduler.d.ts.map +1 -1
- package/dist/async/jobs/scheduler.js +4 -1
- package/dist/async/jobs/scheduler.js.map +1 -1
- package/dist/cli/commands/alerts.d.ts +1 -0
- package/dist/cli/commands/alerts.d.ts.map +1 -1
- package/dist/cli/commands/alerts.js +55 -14
- package/dist/cli/commands/alerts.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +4 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/core/config/schema.js +1 -1
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/surface/worker.d.ts.map +1 -1
- package/dist/core/surface/worker.js +23 -0
- package/dist/core/surface/worker.js.map +1 -1
- package/dist/data/migrate/internal-definitions.d.ts.map +1 -1
- package/dist/data/migrate/internal-definitions.js +2 -1
- package/dist/data/migrate/internal-definitions.js.map +1 -1
- package/dist/data/write/update.d.ts +2 -2
- package/dist/data/write/update.d.ts.map +1 -1
- package/dist/data/write/update.js.map +1 -1
- package/dist/data/write/upsert.d.ts +2 -2
- package/dist/data/write/upsert.d.ts.map +1 -1
- package/dist/data/write/upsert.js.map +1 -1
- package/dist/data/write/values.d.ts +24 -3
- package/dist/data/write/values.d.ts.map +1 -1
- package/dist/infra/alerts/beat.d.ts +39 -0
- package/dist/infra/alerts/beat.d.ts.map +1 -0
- package/dist/infra/alerts/beat.js +91 -0
- package/dist/infra/alerts/beat.js.map +1 -0
- package/dist/infra/alerts/handle.d.ts +2 -0
- package/dist/infra/alerts/handle.d.ts.map +1 -1
- package/dist/infra/alerts/handle.js +14 -1
- package/dist/infra/alerts/handle.js.map +1 -1
- package/dist/infra/alerts/namespace.d.ts +5 -1
- package/dist/infra/alerts/namespace.d.ts.map +1 -1
- package/dist/infra/alerts/namespace.js +5 -1
- package/dist/infra/alerts/namespace.js.map +1 -1
- package/dist/infra/alerts/schema.d.ts +19 -0
- package/dist/infra/alerts/schema.d.ts.map +1 -1
- package/dist/infra/alerts/schema.js +8 -0
- package/dist/infra/alerts/schema.js.map +1 -1
- package/dist/infra/alerts/sources.d.ts +27 -0
- package/dist/infra/alerts/sources.d.ts.map +1 -1
- package/dist/infra/alerts/sources.js +57 -0
- package/dist/infra/alerts/sources.js.map +1 -1
- package/dist/infra/support/handle.d.ts.map +1 -1
- package/dist/infra/support/handle.js +21 -2
- package/dist/infra/support/handle.js.map +1 -1
- package/dist/infra/support/namespace.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/infra/email/sigv4.d.ts +0 -24
- package/dist/infra/email/sigv4.d.ts.map +0 -1
- package/dist/infra/email/sigv4.js +0 -55
- package/dist/infra/email/sigv4.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.172.0
|
|
4
|
+
|
|
5
|
+
- **Added: background loops record when they last ran, and a stopped one raises an alert** (follows #711). The alerts tick, the job scheduler, reaper and claim loop, and the support events drain each upsert a row in the new `pipework_loop_beats` table at the end of every iteration: `last_at`, `last_ok_at`, `last_error`, `expect_every_ms`. Beats are written only where the blueprint has `alerts`, and a failed beat never breaks its loop. A loop is stale when it has not succeeded within `max(3 × its interval, 60 s)`, or within a per-loop `maxAge`.
|
|
6
|
+
- `alerts.source.loopStalled({ maxAge?, exclude?, owner, runbook })` raises `loop-stalled:<name>` ("jobs.reaper has not run in 12 min", or "has not succeeded in …; last error: …") and resolves when the loop beats again. It leaves out `alerts.tick`, which cannot report its own death.
|
|
7
|
+
- The tick is covered from outside it. `pipework alerts stale [--max-age <loop>=<5m> ...]` takes one connection and needs no running app; run it from a systemd timer with `OnFailure=`. It exits 1 and names each stale loop, or exits 1 when no beat was ever recorded. `alerts.loopCheck({ instance })` is a `loops` health check for `/ready`.
|
|
8
|
+
- `AlertsConfig.tickEveryMs` (default 60 000) says how often you schedule the tick. Run your migration generator after upgrading.
|
|
9
|
+
|
|
10
|
+
## 0.171.0
|
|
11
|
+
|
|
12
|
+
- **Fixed: typed writes accept readonly tuples and arrays** (#714). Since typed insert values, a `field.jsonb(check.tuple([...]))` or `field.jsonb(check.array(...))` column refused a `readonly` value (`TS4104: The type 'Box' is 'readonly' and cannot be assigned to the mutable type`), so an app keeping its data readonly had to copy it to insert. `pipe.insert(T).values(...)`, `pipe.upsert(T).values(...)` and `.set(...)` on update and upsert now accept the readonly form of every tuple and array in a column's type, including inside jsonb objects; a wrong length, a wrong element type or an unknown key is still refused. Types only; nothing changes at runtime.
|
|
13
|
+
|
|
3
14
|
## 0.170.0
|
|
4
15
|
|
|
5
16
|
- **Added: `alerts.source.unitFault`, so a crash-looping or OOM-killed service raises an alert** (#711). Add `ExecStopPost=pipework alerts unit-fault --unit %n` (optionally `--database <name>`) to a systemd unit: the command reads `$SERVICE_RESULT`, `$EXIT_CODE` and `$EXIT_STATUS` and, for any stop other than `success` (`oom-kill`, `signal`, `exit-code`, `timeout`, `watchdog`, ...), writes one row to the new `pipework_unit_faults` table over one short connection, with no manifold boot, so it works while the service itself is down. `alerts.source.unitFault({ window, owner, runbook, units? })` raises `unit-fault:<unit>` while a unit has faults within `window` ms, reading `subseam-core: oom-kill x22 in 85 min`, with a context of `{ count, lastResult, lastExitCode, lastExitStatus, firstAt, lastAt }`; it resolves once the window passes with no new fault. The table comes with the `alerts` blueprint flag: run your migration generator after upgrading.
|
package/REFERENCE.md
CHANGED
|
@@ -1730,6 +1730,43 @@ Pass in `sources`; each raises with a fixed key on a tick and, where it can tell
|
|
|
1730
1730
|
- `queue.totals(db)` — `{ overall, byType }`, each `{ ready, running, oldestReadyWaitMs }` (ready: pending and not waiting on a retry time; running: claimed or running; wait from `queued_at`, null when none is ready); `byType` omits a type with neither.
|
|
1731
1731
|
- `alerts.source.health(checks, { severity? = 'error' })` — `health:<name>` while a `HealthCheck` is unhealthy or throws; resolves when it recovers. Degraded is not a fault.
|
|
1732
1732
|
|
|
1733
|
+
#### Loop beats
|
|
1734
|
+
|
|
1735
|
+
Alerts only run while the tick runs, so each background loop records when it last ran in `pipework_loop_beats` (comes with the `alerts` blueprint flag; a loop writes only when the blueprint has `alerts`). One row per name, upserted at the end of each iteration, ok or not, on the loop's own connection and outside any job transaction: `last_at` (always), `last_ok_at` (only when it succeeded), `last_error` (cleared on success), `expect_every_ms`. A failed beat is logged and never breaks the loop.
|
|
1736
|
+
|
|
1737
|
+
| Name | Beat written | Expected every |
|
|
1738
|
+
|---|---|---|
|
|
1739
|
+
| `alerts.tick` | each `handle.tick()` / alerts job | `AlertsConfig.tickEveryMs` (default 60 s; how often you schedule the tick) |
|
|
1740
|
+
| `jobs.scheduler` | each scheduler check | `schedulerIntervalMs` |
|
|
1741
|
+
| `jobs.reaper` | each reaper run | the reaper interval |
|
|
1742
|
+
| `jobs.claim` | the claim loop, at most one per 60 s per process (also while a job runs) | 60 s |
|
|
1743
|
+
| `support.events` | each support events drain | 60 s |
|
|
1744
|
+
|
|
1745
|
+
Several processes share a name: the row is the newest from any of them. A loop is stale when `last_ok_at` is null or older than its allowance, `max(3 * expect_every_ms, 60 s)` unless overridden per name.
|
|
1746
|
+
|
|
1747
|
+
- `alerts.source.loopStalled({ maxAge?: { [name]: ms }, owner?, runbook?, severity? = 'error', exclude?, database? })` — `loop-stalled:<name>` with message `<name> has not run in <age>` or `<name> has not succeeded in <age>; last error: <lastError>` (age like `45 s`, `12 min`, `3 h`), subject `{ entity: 'loop', entityId: name }`, context `{ name, lastAt, lastOkAt, lastError, expectEveryMs, allowanceMs }`. `alerts.tick` is always left out: a stopped tick cannot report itself.
|
|
1748
|
+
- `alerts.loopCheck({ maxAge?, include?, database?, instance? })` — a `HealthCheck` named `loops` for `healthChecks` / `/ready`; unhealthy when any included loop (all by default, `alerts.tick` too) is stale or no beat exists, the message lists the loops and ages. `/ready` runs outside a managed context, so pass `instance`.
|
|
1749
|
+
- `pipework alerts stale [--max-age <name>=<90s|5m|2h> ...] [--database <name>]` — one connection, no manifold boot. Prints `[pipework] stale loop <name>: <message>` per stale loop to stderr and exits 1; exits 0 silently when none is stale; with no beat rows at all prints `[pipework] no loop has ever recorded a beat` and exits 1. This is the check that covers the tick itself.
|
|
1750
|
+
|
|
1751
|
+
Run it from a systemd timer so a dead worker is noticed from outside:
|
|
1752
|
+
|
|
1753
|
+
```ini
|
|
1754
|
+
# pipework-loops.service: fails (exit 1) when a loop is stale; notify-ops@ is your notifier unit
|
|
1755
|
+
[Unit]
|
|
1756
|
+
OnFailure=notify-ops@%n.service
|
|
1757
|
+
[Service]
|
|
1758
|
+
Type=oneshot
|
|
1759
|
+
WorkingDirectory=/srv/app
|
|
1760
|
+
EnvironmentFile=/srv/app/.env
|
|
1761
|
+
ExecStart=pipework alerts stale
|
|
1762
|
+
|
|
1763
|
+
# pipework-loops.timer
|
|
1764
|
+
[Timer]
|
|
1765
|
+
OnCalendar=*:0/5
|
|
1766
|
+
[Install]
|
|
1767
|
+
WantedBy=timers.target
|
|
1768
|
+
```
|
|
1769
|
+
|
|
1733
1770
|
When a source's `evaluate()` throws, the tick raises `alert-source-failed:<source name>` (severity `error`, the error's message) and leaves the source's own alerts open; it resolves when that source next evaluates without throwing.
|
|
1734
1771
|
|
|
1735
1772
|
`table` is the jobs table, default `pipework_jobs`. A custom source is `{ name, evaluate(): Promise<{ key, severity, message, subject? }[]>, owns?(key) }`; with `owns`, an open alert it owns that `evaluate` no longer returns is resolved.
|
package/dist/REFERENCE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Pipework API Reference
|
|
2
2
|
|
|
3
3
|
> Auto-generated from source JSDoc. Do not edit manually.
|
|
4
|
-
> Generated: 2026-10-
|
|
4
|
+
> Generated: 2026-10-20
|
|
5
5
|
|
|
6
6
|
## Contents
|
|
7
7
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
- [jobs — Background Jobs](#jobs-background-jobs)
|
|
11
11
|
- [pipeline — Multi-Step Pipelines](#pipeline-multi-step-pipelines)
|
|
12
12
|
- [state — State Machines](#state-state-machines)
|
|
13
|
+
- [steps](#steps)
|
|
13
14
|
- [auth — Authentication](#auth-authentication)
|
|
14
15
|
- [rbac — Access Control](#rbac-access-control)
|
|
15
16
|
- [tenant — Multi-Tenancy](#tenant-multi-tenancy)
|
|
@@ -30,7 +31,9 @@
|
|
|
30
31
|
- [cache — Caching](#cache-caching)
|
|
31
32
|
- [credits](#credits)
|
|
32
33
|
- [mail](#mail)
|
|
34
|
+
- [untrustedFetch](#untrustedfetch)
|
|
33
35
|
- [storage](#storage)
|
|
36
|
+
- [support](#support)
|
|
34
37
|
- [webhook — Inbound & Outbound Webhooks](#webhook-inbound-outbound-webhooks)
|
|
35
38
|
- [behavior — Resource Decorators](#behavior-resource-decorators)
|
|
36
39
|
- [fitting — Dependency Injection](#fitting-dependency-injection)
|
|
@@ -85,6 +88,18 @@ function createManifold<const TEnv extends EnvDefs = EnvDefs>( raw: Omit<Bluepri
|
|
|
85
88
|
interface Manifold<TEnv extends EnvDefs = EnvDefs>
|
|
86
89
|
```
|
|
87
90
|
|
|
91
|
+
**`ScriptOptions`** — Options for {@link Manifold.script}.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface ScriptOptions
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**`StartOptions`** — Options for {@link Manifold.start}.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
interface StartOptions
|
|
101
|
+
```
|
|
102
|
+
|
|
88
103
|
**`SeedOptions`** — ALS context the {@link Manifold.seed} callback runs under — tenant scope, auth principal, and job type.
|
|
89
104
|
|
|
90
105
|
```typescript
|
|
@@ -229,6 +244,14 @@ Creates a job queue with claim/complete/fail lifecycle, heartbeat, and dead lett
|
|
|
229
244
|
|
|
230
245
|
Executes a fitting handler as a background job with its own Flow context.
|
|
231
246
|
|
|
247
|
+
### `jobs.later`
|
|
248
|
+
|
|
249
|
+
The error to throw to end an attempt as "later": pending again after `delayMs`, no attempt counted.
|
|
250
|
+
|
|
251
|
+
### `jobs.permanent`
|
|
252
|
+
|
|
253
|
+
The error to throw to dead-letter the job now, whatever attempts remain.
|
|
254
|
+
|
|
232
255
|
### `jobs.parseCron`
|
|
233
256
|
|
|
234
257
|
Parses a 5-field cron expression into a CronSchedule (minute, hour, dom, month, dow).
|
|
@@ -269,6 +292,14 @@ Thrown when a transition is not allowed from the current state.
|
|
|
269
292
|
|
|
270
293
|
Thrown when the state machine definition is internally inconsistent.
|
|
271
294
|
|
|
295
|
+
## steps
|
|
296
|
+
|
|
297
|
+
Step graphs over a job queue: results recorded by their inputs, only missing steps run.
|
|
298
|
+
|
|
299
|
+
### `steps.define`
|
|
300
|
+
|
|
301
|
+
Defines a graph of named steps over a jobs Queue. Pass it to `createWorkerSurface({ graphs })` to run its steps.
|
|
302
|
+
|
|
272
303
|
## auth — Authentication
|
|
273
304
|
|
|
274
305
|
Authentication namespace — session management, multi-org support, auth chain resolution.
|
|
@@ -289,6 +320,10 @@ Hashes and verifies passwords with scrypt; reports when a stored hash needs reha
|
|
|
289
320
|
|
|
290
321
|
Guarded password sign-in that slows, then refuses, repeated failures per account and per client.
|
|
291
322
|
|
|
323
|
+
### `auth.emailLinks`
|
|
324
|
+
|
|
325
|
+
Emailed single-use links that prove control of an address: password reset and address verification; the token is never stored.
|
|
326
|
+
|
|
292
327
|
### `auth.runChain`
|
|
293
328
|
|
|
294
329
|
Executes an auth chain (strategy pipeline) to resolve auth + tenant from a request.
|
|
@@ -323,7 +358,7 @@ interface AuthContext
|
|
|
323
358
|
interface AuthStrategy<TAuth>
|
|
324
359
|
```
|
|
325
360
|
|
|
326
|
-
**`AuthRequest`** — Normalized request shape passed to auth strategies — headers,
|
|
361
|
+
**`AuthRequest`** — Normalized request shape passed to auth strategies — headers, the parsed `Cookie` header, and the upper-case HTTP method.
|
|
327
362
|
|
|
328
363
|
```typescript
|
|
329
364
|
interface AuthRequest
|
|
@@ -353,6 +388,18 @@ interface TenantResolver<TAuth>
|
|
|
353
388
|
interface AuthChainConfig<TAuth>
|
|
354
389
|
```
|
|
355
390
|
|
|
391
|
+
**`SessionAuth`** — What `sessions.strategy()` authenticates: the token's user and org, its roles, and where the token came from.
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
type SessionAuth = BaseAuth &
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
**`SessionStrategyOptions`** — Options for `sessions.strategy()`.
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
interface SessionStrategyOptions
|
|
401
|
+
```
|
|
402
|
+
|
|
356
403
|
**`SessionConfig`** — Session configuration — signing keys, issuer, audience, token TTLs, refresh rotation.
|
|
357
404
|
|
|
358
405
|
```typescript
|
|
@@ -624,6 +671,10 @@ Base error class with code, statusCode, and suggestion fields.
|
|
|
624
671
|
|
|
625
672
|
403 — authenticated but insufficient permissions.
|
|
626
673
|
|
|
674
|
+
### `errors.CrossSiteRequest`
|
|
675
|
+
|
|
676
|
+
403 `CROSS_SITE_REQUEST` — a cookie-authenticated write that did not come from the app's own site.
|
|
677
|
+
|
|
627
678
|
### `errors.Validation`
|
|
628
679
|
|
|
629
680
|
422 — input validation failed, carries field-level details.
|
|
@@ -644,13 +695,17 @@ Base error class with code, statusCode, and suggestion fields.
|
|
|
644
695
|
|
|
645
696
|
415 — request body media type not accepted by the route.
|
|
646
697
|
|
|
698
|
+
### `errors.MalformedMultipart`
|
|
699
|
+
|
|
700
|
+
400 `MALFORMED_MULTIPART` — a multipart body that cannot be parsed or ends before its closing boundary.
|
|
701
|
+
|
|
647
702
|
## lifecycle — Startup & Shutdown
|
|
648
703
|
|
|
649
704
|
Application lifecycle namespace — startup orchestration with hooks and timeouts.
|
|
650
705
|
|
|
651
706
|
### `lifecycle.orchestrate`
|
|
652
707
|
|
|
653
|
-
Runs pre-start hooks (DB readiness checks, migrations, etc.) with a configurable timeout.
|
|
708
|
+
Runs pre-start hooks (DB readiness checks, migrations, etc.) with a configurable timeout. The hooks run in one trace that names the process; the trace-partition hook runs first, outside it.
|
|
654
709
|
|
|
655
710
|
## log — Structured Logging
|
|
656
711
|
|
|
@@ -690,7 +745,7 @@ Creates a worker surface — a long-running process that claims and executes job
|
|
|
690
745
|
|
|
691
746
|
### `surface.script`
|
|
692
747
|
|
|
693
|
-
Creates a script surface — a one-shot process that runs and exits (migrations, seeds, CLI tools).
|
|
748
|
+
Creates a script surface — a one-shot process that runs and exits (migrations, seeds, CLI tools). The run is traced as a job-kind trace that names the surface.
|
|
694
749
|
|
|
695
750
|
## pipe — Database
|
|
696
751
|
|
|
@@ -787,7 +842,7 @@ Pipework-owned UPDATE builder — the only consumer-facing way to update pipewor
|
|
|
787
842
|
|
|
788
843
|
### `pipe.insert`
|
|
789
844
|
|
|
790
|
-
Pipework-owned INSERT builder — the only consumer-facing way to insert into pipework-managed tables (Q8).
|
|
845
|
+
Pipework-owned INSERT builder — the only consumer-facing way to insert into pipework-managed tables (Q8). A list of any size is split into statements under Postgres's parameter limit, in one transaction.
|
|
791
846
|
|
|
792
847
|
### `pipe.delete`
|
|
793
848
|
|
|
@@ -795,7 +850,7 @@ Pipework-owned DELETE builder — the only consumer-facing way to delete from pi
|
|
|
795
850
|
|
|
796
851
|
### `pipe.upsert`
|
|
797
852
|
|
|
798
|
-
Pipework-owned UPSERT builder — insert with conflict resolution (Q8).
|
|
853
|
+
Pipework-owned UPSERT builder — insert with conflict resolution (Q8). A list of any size is split into statements under Postgres's parameter limit, in one transaction; rows repeating a conflict key across statements do not fail as one statement would.
|
|
799
854
|
|
|
800
855
|
### Types
|
|
801
856
|
|
|
@@ -947,6 +1002,14 @@ Query all versions of temporal records (no date filter).
|
|
|
947
1002
|
|
|
948
1003
|
Close the current version and create a new one with updated data.
|
|
949
1004
|
|
|
1005
|
+
### `temporal.setVersion`
|
|
1006
|
+
|
|
1007
|
+
Append the next version of an append-only-versions definition: serialised per scope, numbered, never back-dated, audited.
|
|
1008
|
+
|
|
1009
|
+
### `temporal.versionAt`
|
|
1010
|
+
|
|
1011
|
+
The version in force at a moment: the row with the greatest effectiveFrom at or before it.
|
|
1012
|
+
|
|
950
1013
|
## valve
|
|
951
1014
|
|
|
952
1015
|
Valve namespace — typed, directional, gated boundaries between code silos.
|
|
@@ -1129,6 +1192,18 @@ Alerts namespace — raise and resolve keyed conditions, grouped, delivered to s
|
|
|
1129
1192
|
|
|
1130
1193
|
Creates an alerts handle.
|
|
1131
1194
|
|
|
1195
|
+
### `alerts.http`
|
|
1196
|
+
|
|
1197
|
+
Routes for an operations agent: list, get, totals, delivery health, acknowledge, resolve, link; bearer credentials.
|
|
1198
|
+
|
|
1199
|
+
### `alerts.clientFaults`
|
|
1200
|
+
|
|
1201
|
+
One POST route that records failures reported by browser code as a trace step and an alert; answers 204, no session needed. Send with `reportClientFault` from `pipework/client`.
|
|
1202
|
+
|
|
1203
|
+
### `alerts.requestFaults`
|
|
1204
|
+
|
|
1205
|
+
An `onInternalError` hook for the HTTP server: raises `request-fault:<METHOD> <route>` for each internal 500.
|
|
1206
|
+
|
|
1132
1207
|
### `alerts.webhook`
|
|
1133
1208
|
|
|
1134
1209
|
A sink that POSTs the alert as signed JSON to a URL.
|
|
@@ -1161,6 +1236,10 @@ The newest record's `{ seq, hash }` in the tenant's audit hash chain (blueprint
|
|
|
1161
1236
|
|
|
1162
1237
|
Walks the tenant's audit hash chain and reports the first break (hash-mismatch, prev-mismatch, missing, head-mismatch, anchor-mismatch), or `{ ok: true }`.
|
|
1163
1238
|
|
|
1239
|
+
### `audit.removeTenant`
|
|
1240
|
+
|
|
1241
|
+
Deletes every audit record of one tenant and its hash chain, for the closure of that tenant's account. Irreversible; returns the number of records removed. Other tenants' records and chains are untouched.
|
|
1242
|
+
|
|
1164
1243
|
## cache — Caching
|
|
1165
1244
|
|
|
1166
1245
|
In-memory caching namespace — TTL-based with stats, preload, and tenant-aware variants.
|
|
@@ -1213,6 +1292,36 @@ Inbound source: SES receipt rule storing raw messages in S3 and notifying a sign
|
|
|
1213
1292
|
|
|
1214
1293
|
Inbound development source: `.eml` files dropped in a folder, received by `scan()`; refused in production.
|
|
1215
1294
|
|
|
1295
|
+
## untrustedFetch
|
|
1296
|
+
|
|
1297
|
+
Untrusted fetch — fetch one URL a stranger gave without letting them reach the app's private network.
|
|
1298
|
+
|
|
1299
|
+
### `untrustedFetch.get`
|
|
1300
|
+
|
|
1301
|
+
Fetches `url` with GET and returns `{ ok: true, url, status, contentType, body, bytes }`, or `{ ok: false, reason, message }`
|
|
1302
|
+
naming the rule that refused: `scheme`, `address`, `redirects`, `too_large`, `timeout`, `status`, `rejected` or `network`.
|
|
1303
|
+
It does not throw for these.
|
|
1304
|
+
|
|
1305
|
+
Rules, none of which can be switched off: only `http:` and `https:`; the name is resolved and every address is checked
|
|
1306
|
+
(loopback, private, link-local including cloud metadata, CGNAT, unique-local and site-local IPv6, multicast, reserved,
|
|
1307
|
+
unspecified, and IPv4-mapped or NAT64 forms of these; literal IP URLs likewise) and the connection goes to a checked
|
|
1308
|
+
address; redirects are followed up to `maxRedirects` and each hop is checked as the first, and the app's `headers` go only to the first origin;
|
|
1309
|
+
the body is stopped the moment it passes `maxBytes`, whatever Content-Length says; `timeoutMs` covers the whole fetch.
|
|
1310
|
+
`accept({ status, contentType, firstBytes })` sees the first 1024 bytes before the body is kept: return false, or a string
|
|
1311
|
+
(your own message), to refuse with `rejected`. Messages never contain an address or anything a server sent.
|
|
1312
|
+
|
|
1313
|
+
`resolve` and `connect` are for tests: `resolve(hostname)` replaces DNS and `connect(target)` replaces the socket after the
|
|
1314
|
+
address check passed, so a test sends a fake public address to a local server. The address check always runs on what `resolve` returns.
|
|
1315
|
+
|
|
1316
|
+
The call is the trace step `pipework/fetch:get`; its child `pipework/fetch:outcome` carries host, status, bytes and reason.
|
|
1317
|
+
The full URL is recorded only when `urlIsSafeToTrace` is true; otherwise only the host.
|
|
1318
|
+
|
|
1319
|
+
```ts
|
|
1320
|
+
const got = await untrustedFetch.get(pasted, { maxBytes: 5_000_000, timeoutMs: 10_000, maxRedirects: 3,
|
|
1321
|
+
accept: h => h.firstBytes[0] === 0x25 || 'That does not look like a PDF.' })
|
|
1322
|
+
if (!got.ok) return tell(got.message)
|
|
1323
|
+
```
|
|
1324
|
+
|
|
1216
1325
|
## storage
|
|
1217
1326
|
|
|
1218
1327
|
Storage namespace — tenant-scoped, content-addressed file storage with signed URLs and retention.
|
|
@@ -1229,6 +1338,18 @@ S3-compatible backend (AWS S3, MinIO, R2): SigV4 over `fetch`, multipart streami
|
|
|
1229
1338
|
|
|
1230
1339
|
Local-disk backend for development and tests; refused in production.
|
|
1231
1340
|
|
|
1341
|
+
## support
|
|
1342
|
+
|
|
1343
|
+
Support namespace — tickets from email (and later chat), with replies sent only after an approval.
|
|
1344
|
+
|
|
1345
|
+
### `support.create`
|
|
1346
|
+
|
|
1347
|
+
Creates the support handle: tickets, messages, notes, links, drafts, `approve`, `receiveEmail`, and the events job.
|
|
1348
|
+
|
|
1349
|
+
### `support.templates`
|
|
1350
|
+
|
|
1351
|
+
The reply template to spread into `mail.create({ templates })`; it renders the approved draft verbatim.
|
|
1352
|
+
|
|
1232
1353
|
## webhook — Inbound & Outbound Webhooks
|
|
1233
1354
|
|
|
1234
1355
|
Webhook namespace — inbound verification, outbound delivery with retries, HMAC signing.
|
|
@@ -1319,6 +1440,10 @@ Returns the current Flow or undefined — use for optional context detection.
|
|
|
1319
1440
|
|
|
1320
1441
|
Creates a Flow for test isolation with optional auth and tenant overrides.
|
|
1321
1442
|
|
|
1443
|
+
### `flow.actAs`
|
|
1444
|
+
|
|
1445
|
+
Runs `fn` as a tenant and user chosen inside a tenantless Flow (sign-up, a public sign-in): RLS, audit and trace under that tenant, on the request's transaction.
|
|
1446
|
+
|
|
1322
1447
|
## http — Server
|
|
1323
1448
|
|
|
1324
1449
|
HTTP namespace: `http.file()` builds a file response; the server itself is managed by manifold.start().
|
|
@@ -1343,6 +1468,36 @@ interface SecurityConfig
|
|
|
1343
1468
|
interface RateLimitConfig
|
|
1344
1469
|
```
|
|
1345
1470
|
|
|
1471
|
+
**`RateLimitWindow`** — One fixed window: at most `max` requests per `windowSeconds`.
|
|
1472
|
+
|
|
1473
|
+
```typescript
|
|
1474
|
+
interface RateLimitWindow
|
|
1475
|
+
```
|
|
1476
|
+
|
|
1477
|
+
**`RateLimitClass`** — A named limit class: any of a per-user, per-tenant and per-address window, each counted on its own.
|
|
1478
|
+
|
|
1479
|
+
```typescript
|
|
1480
|
+
interface RateLimitClass
|
|
1481
|
+
```
|
|
1482
|
+
|
|
1483
|
+
**`RateLimitRefusal`** — What `onRefused` is told about one refused window of one request.
|
|
1484
|
+
|
|
1485
|
+
```typescript
|
|
1486
|
+
interface RateLimitRefusal
|
|
1487
|
+
```
|
|
1488
|
+
|
|
1489
|
+
**`RateLimitClassesConfig`**
|
|
1490
|
+
|
|
1491
|
+
Named limit classes, checked after auth and counted in Postgres (`pipework_rate_limit_counts`, opted in
|
|
1492
|
+
with the blueprint's `rateLimits: {}`), so every server process on the same database shares one count.
|
|
1493
|
+
Windows are counted perUser, perTenant, perAddress in turn, up to the first one over its max, so one user's
|
|
1494
|
+
refused requests don't spend the tenant's budget. A route is in `signedIn` (auth required, or optional with
|
|
1495
|
+
a user), `public` (no auth, or optional without a user) or the class its fitting names with `.rateLimit(name)`.
|
|
1496
|
+
|
|
1497
|
+
```typescript
|
|
1498
|
+
interface RateLimitClassesConfig
|
|
1499
|
+
```
|
|
1500
|
+
|
|
1346
1501
|
**`InjectOptions`** — Options for server.inject() — method, url, headers, payload for testing without HTTP.
|
|
1347
1502
|
|
|
1348
1503
|
```typescript
|
|
@@ -1361,6 +1516,12 @@ interface InjectResponse
|
|
|
1361
1516
|
interface ServerConfig
|
|
1362
1517
|
```
|
|
1363
1518
|
|
|
1519
|
+
**`InternalErrorFault`** — What `onInternalError` is told about one request that ended in an internal error.
|
|
1520
|
+
|
|
1521
|
+
```typescript
|
|
1522
|
+
interface InternalErrorFault
|
|
1523
|
+
```
|
|
1524
|
+
|
|
1364
1525
|
**`HandlerResponse`** — Standard handler response shape — statusCode, headers, body.
|
|
1365
1526
|
|
|
1366
1527
|
```typescript
|
|
@@ -1419,7 +1580,7 @@ Generates an OpenAPI 3.1 document from route registrations — schemas derived f
|
|
|
1419
1580
|
|
|
1420
1581
|
## trace
|
|
1421
1582
|
|
|
1422
|
-
Trace namespace — hand the current trace to a process outside Node
|
|
1583
|
+
Trace namespace — hand the current trace to a process outside Node, record the steps it reports back, mark point events, and read a trace tree.
|
|
1423
1584
|
|
|
1424
1585
|
### `trace.traceparent`
|
|
1425
1586
|
|
|
@@ -1433,6 +1594,15 @@ W3C `traceparent` for the current trace and open step; `null` outside a traced f
|
|
|
1433
1594
|
|
|
1434
1595
|
Records steps reported as JSON lines (or objects) by an outside process under the step open now. Synchronous; never throws.
|
|
1435
1596
|
|
|
1597
|
+
### `trace.event`
|
|
1598
|
+
|
|
1599
|
+
Records one zero-length step `external:<name>` under the step open now, with an optional `capture` and `error`. A no-op outside a traced flow; never throws.
|
|
1600
|
+
|
|
1601
|
+
### `trace.tree`
|
|
1602
|
+
|
|
1603
|
+
Reads every hot trace sharing `rootId` (a request's trace and the jobs it queued) with their steps. Runs on the
|
|
1604
|
+
given `db`, so tenant policies apply: only an unrestricted connection (table owner, tests) sees every tenant's rows.
|
|
1605
|
+
|
|
1436
1606
|
### Types
|
|
1437
1607
|
|
|
1438
1608
|
**`FlowStepMeta`** — Trace metadata for one documented flow-step: its `path:symbol` graph node id and the per-argument capture projections.
|
|
@@ -1453,6 +1623,24 @@ type ExternalStepReport = z.infer<typeof externalStepReportSchema>
|
|
|
1453
1623
|
interface ExternalRecordResult
|
|
1454
1624
|
```
|
|
1455
1625
|
|
|
1626
|
+
**`TraceStepNode`** — One step of a trace. `ref` is the flow step's `path:symbol`, or `external:<name>` for a recorded or point-event step.
|
|
1627
|
+
|
|
1628
|
+
```typescript
|
|
1629
|
+
interface TraceStepNode
|
|
1630
|
+
```
|
|
1631
|
+
|
|
1632
|
+
**`TraceNode`** — One trace of the tree, with its steps ordered by `seq`.
|
|
1633
|
+
|
|
1634
|
+
```typescript
|
|
1635
|
+
interface TraceNode
|
|
1636
|
+
```
|
|
1637
|
+
|
|
1638
|
+
**`TraceTree`** — The traces that share a root id, ordered by when they opened.
|
|
1639
|
+
|
|
1640
|
+
```typescript
|
|
1641
|
+
interface TraceTree
|
|
1642
|
+
```
|
|
1643
|
+
|
|
1456
1644
|
## data
|
|
1457
1645
|
|
|
1458
1646
|
### `tap`
|
|
@@ -23,6 +23,11 @@ export interface SchedulerOptions {
|
|
|
23
23
|
readonly names?: readonly string[];
|
|
24
24
|
/** Called when a tick throws; without it the error is swallowed so the next tick still runs. */
|
|
25
25
|
readonly onError?: (err: unknown) => void;
|
|
26
|
+
/** Called after every check, whether it succeeded or threw. */
|
|
27
|
+
readonly onCheck?: (outcome: {
|
|
28
|
+
readonly ok: boolean;
|
|
29
|
+
readonly error?: string;
|
|
30
|
+
}) => void;
|
|
26
31
|
}
|
|
27
32
|
export interface Scheduler {
|
|
28
33
|
/** Upserts a schedule. An unchanged cron and timezone keep `next_run_at` and `last_run_at`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/async/jobs/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAA;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACvD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/async/jobs/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAA;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACvD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IACzC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACxF;AAED,MAAM,WAAW,SAAS;IACxB,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,2HAA2H;IAC3H,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAC5F,0GAA0G;IAC1G,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C;;;;;OAKG;IACH,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACxD,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,aAAa,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC9C,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC5C,IAAI,IAAI,IAAI,CAAA;CACb;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CA2JjF"}
|
|
@@ -126,7 +126,10 @@ export function createScheduler(enqueuer, jobsTableQ) {
|
|
|
126
126
|
if (inTick)
|
|
127
127
|
return;
|
|
128
128
|
inTick = true;
|
|
129
|
-
tick(db, opts?.names).
|
|
129
|
+
tick(db, opts?.names).then(() => { opts?.onCheck?.({ ok: true }); }, (err) => {
|
|
130
|
+
opts?.onError?.(err);
|
|
131
|
+
opts?.onCheck?.({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
132
|
+
}).finally(() => { inTick = false; });
|
|
130
133
|
}, intervalMs);
|
|
131
134
|
}
|
|
132
135
|
function stop() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/async/jobs/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAE1C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/async/jobs/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ export interface AlertsOptions {
|
|
|
3
3
|
readonly subcommand: string | undefined;
|
|
4
4
|
readonly unit?: string | undefined;
|
|
5
5
|
readonly database?: string | undefined;
|
|
6
|
+
readonly maxAge?: readonly string[] | undefined;
|
|
6
7
|
}
|
|
7
8
|
export declare function alertsCommand(opts: AlertsOptions): Promise<void>;
|
|
8
9
|
//# sourceMappingURL=alerts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/alerts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/alerts.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CAChD;AASD,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAStE"}
|
|
@@ -1,40 +1,81 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import { bold } from '../output.js';
|
|
3
3
|
import { loadConfig } from './shared/load-config.js';
|
|
4
|
+
import { LOOP_BEATS_QUERY, parseDuration, staleLoops } from '../../infra/alerts/beat.js';
|
|
4
5
|
const CONNECT_TIMEOUT_SECONDS = 5;
|
|
5
6
|
function fail(message) {
|
|
6
7
|
process.stderr.write('[pipework] ' + message + '\n');
|
|
7
8
|
process.exit(1);
|
|
8
9
|
}
|
|
9
10
|
export async function alertsCommand(opts) {
|
|
10
|
-
if (opts.subcommand !== 'unit-fault') {
|
|
11
|
+
if (opts.subcommand !== 'unit-fault' && opts.subcommand !== 'stale') {
|
|
11
12
|
process.stderr.write('[pipework] Unknown alerts subcommand: ' + (opts.subcommand ?? '(none)') + '\n');
|
|
12
|
-
process.stderr.write('\n Usage: ' + bold('pipework alerts unit-fault --unit <name> [--database <name>]') + '\n
|
|
13
|
+
process.stderr.write('\n Usage: ' + bold('pipework alerts unit-fault --unit <name> [--database <name>]') + '\n');
|
|
14
|
+
process.stderr.write(' ' + bold('pipework alerts stale [--max-age <loop>=<90s|5m|2h> ...] [--database <name>]') + '\n\n');
|
|
13
15
|
process.exit(1);
|
|
14
16
|
}
|
|
15
|
-
|
|
17
|
+
if (opts.subcommand === 'stale')
|
|
18
|
+
await stale(opts);
|
|
19
|
+
else
|
|
20
|
+
await unitFault(opts);
|
|
16
21
|
}
|
|
17
|
-
/**
|
|
18
|
-
async function
|
|
19
|
-
if (opts.unit === undefined || opts.unit === '') {
|
|
20
|
-
process.stderr.write('[pipework] alerts unit-fault needs --unit.\n');
|
|
21
|
-
process.stderr.write('\n Usage: ' + bold('pipework alerts unit-fault --unit <name> [--database <name>]') + '\n\n');
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
24
|
-
const result = process.env['SERVICE_RESULT'];
|
|
25
|
-
if (result === undefined || result === '' || result === 'success')
|
|
26
|
-
return;
|
|
22
|
+
/** Resolves the database url from the config the way both subcommands do. */
|
|
23
|
+
async function databaseUrl(opts, command) {
|
|
27
24
|
const { config } = await loadConfig(resolve(opts.cwd));
|
|
28
25
|
const names = Object.keys(config.databases);
|
|
29
26
|
const name = opts.database ?? config.defaultDatabase ?? (names.length === 1 ? names[0] : undefined);
|
|
30
27
|
if (name === undefined)
|
|
31
|
-
fail('alerts
|
|
28
|
+
fail('alerts ' + command + ' needs --database; declared databases: ' + names.join(', ') + '.');
|
|
32
29
|
const dbConfig = config.databases[name];
|
|
33
30
|
if (dbConfig === undefined)
|
|
34
31
|
fail('Database "' + name + '" not found in config. Available: ' + names.join(', ') + '.');
|
|
35
32
|
const url = process.env[dbConfig.url];
|
|
36
33
|
if (url === undefined || url === '')
|
|
37
34
|
fail('Environment variable ' + dbConfig.url + ' for database "' + name + '" is not set.');
|
|
35
|
+
return url;
|
|
36
|
+
}
|
|
37
|
+
/** Prints each stale background loop to stderr and exits 1; silent and 0 when every loop is fresh. Run it from a systemd timer: it needs no running app. */
|
|
38
|
+
async function stale(opts) {
|
|
39
|
+
const maxAge = {};
|
|
40
|
+
for (const spec of opts.maxAge ?? []) {
|
|
41
|
+
const at = spec.indexOf('=');
|
|
42
|
+
const ms = at > 0 ? parseDuration(spec.slice(at + 1)) : null;
|
|
43
|
+
if (ms === null)
|
|
44
|
+
fail('alerts stale --max-age wants <loop>=<duration> such as jobs.claim=5m (units s, m, h); got "' + spec + '".');
|
|
45
|
+
maxAge[spec.slice(0, at)] = ms;
|
|
46
|
+
}
|
|
47
|
+
const url = await databaseUrl(opts, 'stale');
|
|
48
|
+
const { default: postgres } = await import('postgres');
|
|
49
|
+
const client = postgres(url, { max: 1, connect_timeout: CONNECT_TIMEOUT_SECONDS, onnotice: () => { } });
|
|
50
|
+
let rows;
|
|
51
|
+
try {
|
|
52
|
+
rows = [...await client.unsafe(LOOP_BEATS_QUERY)];
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
await client.end({ timeout: 1 }).catch(() => undefined);
|
|
56
|
+
fail('alerts stale could not read the loop beats: ' + (err instanceof Error ? err.message : String(err)).split('\n')[0]);
|
|
57
|
+
}
|
|
58
|
+
await client.end({ timeout: 1 });
|
|
59
|
+
if (rows.length === 0)
|
|
60
|
+
fail('no loop has ever recorded a beat');
|
|
61
|
+
const found = staleLoops(rows, { maxAge });
|
|
62
|
+
if (found.length === 0)
|
|
63
|
+
return;
|
|
64
|
+
for (const l of found)
|
|
65
|
+
process.stderr.write('[pipework] stale loop ' + l.name + ': ' + l.message + '\n');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
/** Records one abnormal stop from systemd's $SERVICE_RESULT, $EXIT_CODE and $EXIT_STATUS over a single short connection; a clean stop writes nothing. */
|
|
69
|
+
async function unitFault(opts) {
|
|
70
|
+
if (opts.unit === undefined || opts.unit === '') {
|
|
71
|
+
process.stderr.write('[pipework] alerts unit-fault needs --unit.\n');
|
|
72
|
+
process.stderr.write('\n Usage: ' + bold('pipework alerts unit-fault --unit <name> [--database <name>]') + '\n\n');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
const result = process.env['SERVICE_RESULT'];
|
|
76
|
+
if (result === undefined || result === '' || result === 'success')
|
|
77
|
+
return;
|
|
78
|
+
const url = await databaseUrl(opts, 'unit-fault');
|
|
38
79
|
const { default: postgres } = await import('postgres');
|
|
39
80
|
const client = postgres(url, { max: 1, connect_timeout: CONNECT_TIMEOUT_SECONDS, onnotice: () => { } });
|
|
40
81
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../../src/cli/commands/alerts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../../src/cli/commands/alerts.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAyEA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2LvD"}
|