pipework 0.68.0 → 0.70.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 +12 -0
- package/REFERENCE.md +98 -1
- package/dist/core/config/namespace.d.ts +1 -0
- package/dist/core/config/namespace.d.ts.map +1 -1
- package/dist/core/config/schema.d.ts +3 -0
- package/dist/core/config/schema.d.ts.map +1 -1
- package/dist/core/config/schema.js +3 -1
- package/dist/core/config/schema.js.map +1 -1
- package/dist/data/migrate/internal-definitions.d.ts.map +1 -1
- package/dist/data/migrate/internal-definitions.js +8 -1
- package/dist/data/migrate/internal-definitions.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/infra/access-links/index.d.ts +1 -0
- package/dist/infra/access-links/index.d.ts.map +1 -1
- package/dist/infra/access-links/namespace.d.ts +24 -0
- package/dist/infra/access-links/namespace.d.ts.map +1 -1
- package/dist/infra/access-links/namespace.js +23 -0
- package/dist/infra/access-links/namespace.js.map +1 -1
- package/dist/infra/access-links/person-check.d.ts +45 -0
- package/dist/infra/access-links/person-check.d.ts.map +1 -0
- package/dist/infra/access-links/person-check.js +128 -0
- package/dist/infra/access-links/person-check.js.map +1 -0
- package/dist/infra/access-links/schema.d.ts +8 -0
- package/dist/infra/access-links/schema.d.ts.map +1 -1
- package/dist/infra/access-links/schema.js +7 -1
- package/dist/infra/access-links/schema.js.map +1 -1
- package/dist/infra/alerts/audit.d.ts +3 -0
- package/dist/infra/alerts/audit.d.ts.map +1 -0
- package/dist/infra/alerts/audit.js +25 -0
- package/dist/infra/alerts/audit.js.map +1 -0
- package/dist/infra/alerts/handle.d.ts +95 -0
- package/dist/infra/alerts/handle.d.ts.map +1 -0
- package/dist/infra/alerts/handle.js +301 -0
- package/dist/infra/alerts/handle.js.map +1 -0
- package/dist/infra/alerts/index.d.ts +5 -0
- package/dist/infra/alerts/index.d.ts.map +1 -0
- package/dist/infra/alerts/index.js +2 -0
- package/dist/infra/alerts/index.js.map +1 -0
- package/dist/infra/alerts/namespace.d.ts +23 -0
- package/dist/infra/alerts/namespace.d.ts.map +1 -0
- package/dist/infra/alerts/namespace.js +23 -0
- package/dist/infra/alerts/namespace.js.map +1 -0
- package/dist/infra/alerts/schema.d.ts +123 -0
- package/dist/infra/alerts/schema.d.ts.map +1 -0
- package/dist/infra/alerts/schema.js +55 -0
- package/dist/infra/alerts/schema.js.map +1 -0
- package/dist/infra/alerts/sinks.d.ts +60 -0
- package/dist/infra/alerts/sinks.d.ts.map +1 -0
- package/dist/infra/alerts/sinks.js +50 -0
- package/dist/infra/alerts/sinks.js.map +1 -0
- package/dist/infra/alerts/sources.d.ts +55 -0
- package/dist/infra/alerts/sources.d.ts.map +1 -0
- package/dist/infra/alerts/sources.js +134 -0
- package/dist/infra/alerts/sources.js.map +1 -0
- package/dist/infra/email/sns.d.ts +1 -1
- package/dist/infra/email/sns.js +1 -1
- package/dist/infra/webhook/sign.d.ts +2 -0
- package/dist/infra/webhook/sign.d.ts.map +1 -1
- package/dist/infra/webhook/sign.js +1 -1
- package/dist/infra/webhook/sign.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle.js","sourceRoot":"","sources":["../../../src/infra/alerts/handle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createAlerts } from './handle.js';
|
|
2
|
+
export type { Alerts, AlertsConfig, Alert, AlertSeverity, AlertSubject, RaiseOptions, DeliveryRow, TickResult, } from './handle.js';
|
|
3
|
+
export type { AlertSink, AlertDelivery, AlertPayload, AlertWebhookConfig, MemoryAlertSink } from './sinks.js';
|
|
4
|
+
export type { AlertSource, AlertCondition } from './sources.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EACV,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,GAChG,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC7G,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/infra/alerts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createAlerts } from './handle.js';
|
|
2
|
+
import { webhookSink, memorySink } from './sinks.js';
|
|
3
|
+
import { deadLetterSource, longRunningSource, backlogSource, healthSource } from './sources.js';
|
|
4
|
+
/** Alerts namespace — raise and resolve keyed conditions, grouped, delivered to sinks through an outbox, traced. */
|
|
5
|
+
export declare const alerts: {
|
|
6
|
+
/** Creates an alerts handle. */
|
|
7
|
+
readonly create: typeof createAlerts;
|
|
8
|
+
/** A sink that POSTs the alert as signed JSON to a URL. */
|
|
9
|
+
readonly webhook: typeof webhookSink;
|
|
10
|
+
/** A sink that keeps deliveries in `.delivered`, for tests. */
|
|
11
|
+
readonly memory: typeof memorySink;
|
|
12
|
+
readonly source: {
|
|
13
|
+
/** Raises `job-dead-letter:<jobType>` for jobs that ran out of attempts. */
|
|
14
|
+
readonly deadLetter: typeof deadLetterSource;
|
|
15
|
+
/** Raises `job-long-running:<jobType>` while a job has been claimed too long. */
|
|
16
|
+
readonly longRunning: typeof longRunningSource;
|
|
17
|
+
/** Raises `queue-backlog:<jobType>` while too many jobs wait or the oldest has waited too long. */
|
|
18
|
+
readonly backlog: typeof backlogSource;
|
|
19
|
+
/** Raises `health:<name>` while a health check fails. */
|
|
20
|
+
readonly health: typeof healthSource;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=namespace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE/F,oHAAoH;AACpH,eAAO,MAAM,MAAM;IACjB,gCAAgC;;IAEhC,2DAA2D;;IAE3D,+DAA+D;;;QAG7D,4EAA4E;;QAE5E,iFAAiF;;QAEjF,mGAAmG;;QAEnG,yDAAyD;;;CAGnD,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createAlerts } from './handle.js';
|
|
2
|
+
import { webhookSink, memorySink } from './sinks.js';
|
|
3
|
+
import { deadLetterSource, longRunningSource, backlogSource, healthSource } from './sources.js';
|
|
4
|
+
/** Alerts namespace — raise and resolve keyed conditions, grouped, delivered to sinks through an outbox, traced. */
|
|
5
|
+
export const alerts = {
|
|
6
|
+
/** Creates an alerts handle. */
|
|
7
|
+
create: createAlerts,
|
|
8
|
+
/** A sink that POSTs the alert as signed JSON to a URL. */
|
|
9
|
+
webhook: webhookSink,
|
|
10
|
+
/** A sink that keeps deliveries in `.delivered`, for tests. */
|
|
11
|
+
memory: memorySink,
|
|
12
|
+
source: {
|
|
13
|
+
/** Raises `job-dead-letter:<jobType>` for jobs that ran out of attempts. */
|
|
14
|
+
deadLetter: deadLetterSource,
|
|
15
|
+
/** Raises `job-long-running:<jobType>` while a job has been claimed too long. */
|
|
16
|
+
longRunning: longRunningSource,
|
|
17
|
+
/** Raises `queue-backlog:<jobType>` while too many jobs wait or the oldest has waited too long. */
|
|
18
|
+
backlog: backlogSource,
|
|
19
|
+
/** Raises `health:<name>` while a health check fails. */
|
|
20
|
+
health: healthSource,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=namespace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace.js","sourceRoot":"","sources":["../../../src/infra/alerts/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE/F,oHAAoH;AACpH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,gCAAgC;IAChC,MAAM,EAAE,YAAY;IACpB,2DAA2D;IAC3D,OAAO,EAAE,WAAW;IACpB,+DAA+D;IAC/D,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE;QACN,4EAA4E;QAC5E,UAAU,EAAE,gBAAgB;QAC5B,iFAAiF;QACjF,WAAW,EAAE,iBAAiB;QAC9B,mGAAmG;QACnG,OAAO,EAAE,aAAa;QACtB,yDAAyD;QACzD,MAAM,EAAE,YAAY;KACrB;CACO,CAAA"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
export declare const ALERT_STATUSES: readonly ["open", "resolved"];
|
|
2
|
+
export declare const ALERT_SEVERITIES: readonly ["info", "warning", "error", "critical"];
|
|
3
|
+
export declare const ALERT_DELIVERY_KINDS: readonly ["raise", "repeat", "resolve"];
|
|
4
|
+
export declare const alerts: import("../../data/domain/types.js").DefinedTable<{
|
|
5
|
+
key: import("../../data/domain/types.js").FieldDescriptor<string, {
|
|
6
|
+
primaryKey: true;
|
|
7
|
+
}> & import("../../data/domain/field.js").FieldModifiers<string, {
|
|
8
|
+
primaryKey: true;
|
|
9
|
+
}>;
|
|
10
|
+
status: import("../../data/domain/types.js").FieldDescriptor<"open" | "resolved", {
|
|
11
|
+
hasDefault: true;
|
|
12
|
+
}> & import("../../data/domain/field.js").FieldModifiers<"open" | "resolved", {
|
|
13
|
+
hasDefault: true;
|
|
14
|
+
}>;
|
|
15
|
+
severity: import("../../data/domain/types.js").FieldDescriptor<"error" | "info" | "warning" | "critical", {}> & import("../../data/domain/field.js").FieldModifiers<"error" | "info" | "warning" | "critical", {}>;
|
|
16
|
+
message: import("../../data/domain/types.js").FieldDescriptor<string, {}> & import("../../data/domain/field.js").FieldModifiers<string, {}>;
|
|
17
|
+
subject: import("../../data/domain/types.js").FieldDescriptor<import("zod/v4").JSONType, {
|
|
18
|
+
nullable: true;
|
|
19
|
+
}> & import("../../data/domain/field.js").FieldModifiers<import("zod/v4").JSONType, {
|
|
20
|
+
nullable: true;
|
|
21
|
+
}>;
|
|
22
|
+
count: import("../../data/domain/types.js").FieldDescriptor<number, {
|
|
23
|
+
hasDefault: true;
|
|
24
|
+
}> & import("../../data/domain/field.js").FieldModifiers<number, {
|
|
25
|
+
hasDefault: true;
|
|
26
|
+
}>;
|
|
27
|
+
firstSeenAt: import("../../data/domain/types.js").FieldDescriptor<Date, {
|
|
28
|
+
hasDefault: true;
|
|
29
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date, {
|
|
30
|
+
hasDefault: true;
|
|
31
|
+
}>;
|
|
32
|
+
lastSeenAt: import("../../data/domain/types.js").FieldDescriptor<Date, {
|
|
33
|
+
hasDefault: true;
|
|
34
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date, {
|
|
35
|
+
hasDefault: true;
|
|
36
|
+
}>;
|
|
37
|
+
lastSentAt: import("../../data/domain/types.js").FieldDescriptor<Date | null, {
|
|
38
|
+
nullable: true;
|
|
39
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date | null, {
|
|
40
|
+
nullable: true;
|
|
41
|
+
}>;
|
|
42
|
+
resolvedAt: import("../../data/domain/types.js").FieldDescriptor<Date | null, {
|
|
43
|
+
nullable: true;
|
|
44
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date | null, {
|
|
45
|
+
nullable: true;
|
|
46
|
+
}>;
|
|
47
|
+
traceIds: import("../../data/domain/types.js").FieldDescriptor<string[], {
|
|
48
|
+
hasDefault: true;
|
|
49
|
+
}> & import("../../data/domain/field.js").FieldModifiers<string[], {
|
|
50
|
+
hasDefault: true;
|
|
51
|
+
}>;
|
|
52
|
+
resendAfterMs: import("../../data/domain/types.js").FieldDescriptor<number | null, {
|
|
53
|
+
nullable: true;
|
|
54
|
+
}> & import("../../data/domain/field.js").FieldModifiers<number | null, {
|
|
55
|
+
nullable: true;
|
|
56
|
+
}>;
|
|
57
|
+
resolveAfterQuietMs: import("../../data/domain/types.js").FieldDescriptor<number | null, {
|
|
58
|
+
nullable: true;
|
|
59
|
+
}> & import("../../data/domain/field.js").FieldModifiers<number | null, {
|
|
60
|
+
nullable: true;
|
|
61
|
+
}>;
|
|
62
|
+
updatedAt: import("../../data/domain/types.js").FieldDescriptor<Date, {
|
|
63
|
+
hasDefault: true;
|
|
64
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date, {
|
|
65
|
+
hasDefault: true;
|
|
66
|
+
}>;
|
|
67
|
+
}, "pipework_alerts">;
|
|
68
|
+
export declare const alertDeliveries: import("../../data/domain/types.js").DefinedTable<{
|
|
69
|
+
id: import("../../data/domain/types.js").FieldDescriptor<string, {
|
|
70
|
+
defaultRandom: true;
|
|
71
|
+
hasDefault: true;
|
|
72
|
+
} & {
|
|
73
|
+
primaryKey: true;
|
|
74
|
+
}> & import("../../data/domain/field.js").FieldModifiers<string, {
|
|
75
|
+
defaultRandom: true;
|
|
76
|
+
hasDefault: true;
|
|
77
|
+
} & {
|
|
78
|
+
primaryKey: true;
|
|
79
|
+
}>;
|
|
80
|
+
alertKey: import("../../data/domain/types.js").FieldDescriptor<string, {}> & import("../../data/domain/field.js").FieldModifiers<string, {}>;
|
|
81
|
+
kind: import("../../data/domain/types.js").FieldDescriptor<"repeat" | "raise" | "resolve", {}> & import("../../data/domain/field.js").FieldModifiers<"repeat" | "raise" | "resolve", {}>;
|
|
82
|
+
sink: import("../../data/domain/types.js").FieldDescriptor<string, {}> & import("../../data/domain/field.js").FieldModifiers<string, {}>;
|
|
83
|
+
payload: import("../../data/domain/types.js").FieldDescriptor<import("zod/v4").JSONType, {}> & import("../../data/domain/field.js").FieldModifiers<import("zod/v4").JSONType, {}>;
|
|
84
|
+
attempts: import("../../data/domain/types.js").FieldDescriptor<number, {
|
|
85
|
+
hasDefault: true;
|
|
86
|
+
}> & import("../../data/domain/field.js").FieldModifiers<number, {
|
|
87
|
+
hasDefault: true;
|
|
88
|
+
}>;
|
|
89
|
+
nextAttemptAt: import("../../data/domain/types.js").FieldDescriptor<Date, {
|
|
90
|
+
hasDefault: true;
|
|
91
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date, {
|
|
92
|
+
hasDefault: true;
|
|
93
|
+
}>;
|
|
94
|
+
deliveredAt: import("../../data/domain/types.js").FieldDescriptor<Date | null, {
|
|
95
|
+
nullable: true;
|
|
96
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date | null, {
|
|
97
|
+
nullable: true;
|
|
98
|
+
}>;
|
|
99
|
+
failedAt: import("../../data/domain/types.js").FieldDescriptor<Date | null, {
|
|
100
|
+
nullable: true;
|
|
101
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date | null, {
|
|
102
|
+
nullable: true;
|
|
103
|
+
}>;
|
|
104
|
+
lastError: import("../../data/domain/types.js").FieldDescriptor<string | null, {
|
|
105
|
+
nullable: true;
|
|
106
|
+
}> & import("../../data/domain/field.js").FieldModifiers<string | null, {
|
|
107
|
+
nullable: true;
|
|
108
|
+
}>;
|
|
109
|
+
createdAt: import("../../data/domain/types.js").FieldDescriptor<Date, {
|
|
110
|
+
hasDefault: true;
|
|
111
|
+
}> & import("../../data/domain/field.js").FieldModifiers<Date, {
|
|
112
|
+
hasDefault: true;
|
|
113
|
+
}>;
|
|
114
|
+
}, "pipework_alert_deliveries">;
|
|
115
|
+
export declare const alertSourceState: import("../../data/domain/types.js").DefinedTable<{
|
|
116
|
+
name: import("../../data/domain/types.js").FieldDescriptor<string, {
|
|
117
|
+
primaryKey: true;
|
|
118
|
+
}> & import("../../data/domain/field.js").FieldModifiers<string, {
|
|
119
|
+
primaryKey: true;
|
|
120
|
+
}>;
|
|
121
|
+
cursorAt: import("../../data/domain/types.js").FieldDescriptor<Date, {}> & import("../../data/domain/field.js").FieldModifiers<Date, {}>;
|
|
122
|
+
}, "pipework_alert_source_state">;
|
|
123
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/schema.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,cAAc,+BAAgC,CAAA;AAC3D,eAAO,MAAM,gBAAgB,mDAAoD,CAAA;AACjF,eAAO,MAAM,oBAAoB,yCAA0C,CAAA;AAE3E,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmBjB,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAmB1B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;iCAG3B,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// The tables behind alerts: one row per alert key, the outbox of deliveries (one row per
|
|
2
|
+
// event and sink), and the cursor a source keeps between evaluations. Not tenant-scoped.
|
|
3
|
+
import { define } from '../../data/domain/index.js';
|
|
4
|
+
import { field } from '../../data/domain/field.js';
|
|
5
|
+
import { schema } from '../../data/schema/namespace.js';
|
|
6
|
+
import { index } from '../../data/db/idx/index.js';
|
|
7
|
+
import { sql } from '../../data/db/sql.js';
|
|
8
|
+
export const ALERT_STATUSES = ['open', 'resolved'];
|
|
9
|
+
export const ALERT_SEVERITIES = ['info', 'warning', 'error', 'critical'];
|
|
10
|
+
export const ALERT_DELIVERY_KINDS = ['raise', 'repeat', 'resolve'];
|
|
11
|
+
export const alerts = define('pipework_alerts', {
|
|
12
|
+
key: field.text().primaryKey(),
|
|
13
|
+
status: field.enum(ALERT_STATUSES).default('open'),
|
|
14
|
+
severity: field.enum(ALERT_SEVERITIES),
|
|
15
|
+
message: field.text(),
|
|
16
|
+
subject: field.jsonb(schema.check.json()).nullable(),
|
|
17
|
+
count: field.integer().default(1),
|
|
18
|
+
firstSeenAt: field.timestamp().default('now'),
|
|
19
|
+
lastSeenAt: field.timestamp().default('now'),
|
|
20
|
+
lastSentAt: field.timestamp().nullable(),
|
|
21
|
+
resolvedAt: field.timestamp().nullable(),
|
|
22
|
+
traceIds: field.custom(schema.col.text('trace_ids').array(), schema.check.array(schema.check.string())).default('{}'),
|
|
23
|
+
resendAfterMs: field.integer().nullable(),
|
|
24
|
+
resolveAfterQuietMs: field.integer().nullable(),
|
|
25
|
+
updatedAt: field.timestamp().default('now'),
|
|
26
|
+
}, {
|
|
27
|
+
indexes: (t) => ({
|
|
28
|
+
byStatus: index('idx_pipework_alerts_status').on(t['status']),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
export const alertDeliveries = define('pipework_alert_deliveries', {
|
|
32
|
+
id: field.uuid().defaultRandom().primaryKey(),
|
|
33
|
+
alertKey: field.text(),
|
|
34
|
+
kind: field.enum(ALERT_DELIVERY_KINDS),
|
|
35
|
+
sink: field.text(),
|
|
36
|
+
payload: field.jsonb(schema.check.json()),
|
|
37
|
+
attempts: field.integer().default(0),
|
|
38
|
+
nextAttemptAt: field.timestamp().default('now'),
|
|
39
|
+
deliveredAt: field.timestamp().nullable(),
|
|
40
|
+
failedAt: field.timestamp().nullable(),
|
|
41
|
+
lastError: field.text().nullable(),
|
|
42
|
+
createdAt: field.timestamp().default('now'),
|
|
43
|
+
}, {
|
|
44
|
+
indexes: (t) => ({
|
|
45
|
+
due: index('idx_pipework_alert_deliveries_due')
|
|
46
|
+
.on(t['nextAttemptAt'])
|
|
47
|
+
.where(sql.raw('delivered_at IS NULL AND failed_at IS NULL')),
|
|
48
|
+
byKey: index('idx_pipework_alert_deliveries_key').on(t['alertKey']),
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
export const alertSourceState = define('pipework_alert_source_state', {
|
|
52
|
+
name: field.text().primaryKey(),
|
|
53
|
+
cursorAt: field.timestamp(),
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/infra/alerts/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { WebhookSignatureOptions } from '../webhook/sign.js';
|
|
2
|
+
/** What a sink receives, and what the webhook sink POSTs as its body. */
|
|
3
|
+
export interface AlertPayload {
|
|
4
|
+
readonly kind: 'raise' | 'repeat' | 'resolve';
|
|
5
|
+
readonly key: string;
|
|
6
|
+
readonly severity: 'info' | 'warning' | 'error' | 'critical';
|
|
7
|
+
readonly message: string;
|
|
8
|
+
readonly subject: {
|
|
9
|
+
readonly tenantId?: string;
|
|
10
|
+
readonly entity?: string;
|
|
11
|
+
readonly entityId?: string;
|
|
12
|
+
} | null;
|
|
13
|
+
readonly count: number;
|
|
14
|
+
readonly firstSeenAt: string;
|
|
15
|
+
readonly lastSeenAt: string;
|
|
16
|
+
readonly resolvedAt: string | null;
|
|
17
|
+
/** The latest traces that raised it, newest first. */
|
|
18
|
+
readonly traceIds: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
export interface AlertDelivery {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly kind: AlertPayload['kind'];
|
|
23
|
+
readonly key: string;
|
|
24
|
+
readonly sink: string;
|
|
25
|
+
readonly payload: AlertPayload;
|
|
26
|
+
/** 1 on the first try. */
|
|
27
|
+
readonly attempt: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A place alerts are sent. `send` throwing is a failed attempt; so is running past 10 s, which is all the
|
|
31
|
+
* handle gives a send (the row is leased for 30 s). `delivery.id` is the same on every attempt, so a receiver can dedupe on it.
|
|
32
|
+
*/
|
|
33
|
+
export interface AlertSink {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
send(delivery: AlertDelivery): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export interface AlertWebhookConfig {
|
|
38
|
+
/** Sink name; default `'webhook'`. Two sinks on one handle need distinct names. */
|
|
39
|
+
readonly name?: string;
|
|
40
|
+
readonly url: string;
|
|
41
|
+
readonly secret: string;
|
|
42
|
+
/** Request timeout; default 10 000, at most 20 000 (the handle gives a send 10 s and leases the row for 30 s). */
|
|
43
|
+
readonly timeoutMs?: number;
|
|
44
|
+
readonly signing?: WebhookSignatureOptions;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* POSTs the payload as JSON with `X-Webhook-Id`, `X-Webhook-Timestamp` and `X-Webhook-Signature`
|
|
48
|
+
* (`X-Webhook-Id` is the delivery id, the same on every attempt; HMAC over `<id>.<timestamp>.<body>`, as `webhook.sign` makes them). Any non-2xx status fails the attempt.
|
|
49
|
+
*/
|
|
50
|
+
export declare function webhookSink(config: AlertWebhookConfig): AlertSink;
|
|
51
|
+
export interface MemoryAlertSink extends AlertSink {
|
|
52
|
+
/** Every delivery received, in order. */
|
|
53
|
+
readonly delivered: AlertDelivery[];
|
|
54
|
+
clear(): void;
|
|
55
|
+
}
|
|
56
|
+
/** A sink that keeps what it receives, for tests. */
|
|
57
|
+
export declare function memorySink(options?: {
|
|
58
|
+
name?: string;
|
|
59
|
+
}): MemoryAlertSink;
|
|
60
|
+
//# sourceMappingURL=sinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinks.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/sinks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AAEjE,yEAAyE;AACzE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAA;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAA;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC7G,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;IAC9B,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,IAAI,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7C;AAED,MAAM,WAAW,kBAAkB;IACjC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,kHAAkH;IAClH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,uBAAuB,CAAA;CAC3C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,CA8BjE;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,aAAa,EAAE,CAAA;IACnC,KAAK,IAAI,IAAI,CAAA;CACd;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,eAAe,CAS3E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { signPayload } from '../webhook/sign.js';
|
|
2
|
+
/**
|
|
3
|
+
* POSTs the payload as JSON with `X-Webhook-Id`, `X-Webhook-Timestamp` and `X-Webhook-Signature`
|
|
4
|
+
* (`X-Webhook-Id` is the delivery id, the same on every attempt; HMAC over `<id>.<timestamp>.<body>`, as `webhook.sign` makes them). Any non-2xx status fails the attempt.
|
|
5
|
+
*/
|
|
6
|
+
export function webhookSink(config) {
|
|
7
|
+
const timeoutMs = config.timeoutMs ?? 10_000;
|
|
8
|
+
if (timeoutMs > 20_000) {
|
|
9
|
+
throw new Error(`[pipework] alerts.webhook: timeoutMs ${String(timeoutMs)} is over 20000. A delivery is leased for 30 s while it is sent; a longer send could be picked up and sent twice.`);
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
name: config.name ?? 'webhook',
|
|
13
|
+
async send(delivery) {
|
|
14
|
+
const signed = signPayload(delivery.payload, config.secret, { ...config.signing, messageId: delivery.id });
|
|
15
|
+
const controller = new AbortController();
|
|
16
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(config.url, {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
'X-Webhook-Id': signed.messageId,
|
|
23
|
+
'X-Webhook-Timestamp': signed.timestamp.toString(),
|
|
24
|
+
'X-Webhook-Signature': signed.signature,
|
|
25
|
+
},
|
|
26
|
+
body: signed.body,
|
|
27
|
+
signal: controller.signal,
|
|
28
|
+
});
|
|
29
|
+
await response.text().catch(() => '');
|
|
30
|
+
if (response.status < 200 || response.status >= 300)
|
|
31
|
+
throw new Error(`webhook answered HTTP ${String(response.status)}`);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** A sink that keeps what it receives, for tests. */
|
|
40
|
+
export function memorySink(options = {}) {
|
|
41
|
+
const delivered = [];
|
|
42
|
+
return {
|
|
43
|
+
name: options.name ?? 'memory',
|
|
44
|
+
delivered,
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- the sink contract is async
|
|
46
|
+
async send(delivery) { delivered.push(delivery); },
|
|
47
|
+
clear() { delivered.length = 0; },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=sinks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinks.js","sourceRoot":"","sources":["../../../src/infra/alerts/sinks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AA+ChD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAA0B;IACpD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAA;IAC5C,IAAI,SAAS,GAAG,MAAM,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,CAAC,SAAS,CAAC,kHAAkH,CAAC,CAAA;IAC9L,CAAC;IACD,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,SAAS;QAC9B,KAAK,CAAC,IAAI,CAAC,QAAQ;YACjB,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAA;YAC1G,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;YACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAA;YAC7D,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE;oBACvC,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,cAAc,EAAE,MAAM,CAAC,SAAS;wBAChC,qBAAqB,EAAE,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE;wBAClD,qBAAqB,EAAE,MAAM,CAAC,SAAS;qBACxC;oBACD,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B,CAAC,CAAA;gBACF,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;gBACrC,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG;oBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC1H,CAAC;oBAAS,CAAC;gBACT,YAAY,CAAC,KAAK,CAAC,CAAA;YACrB,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAQD,qDAAqD;AACrD,MAAM,UAAU,UAAU,CAAC,UAA6B,EAAE;IACxD,MAAM,SAAS,GAAoB,EAAE,CAAA;IACrC,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,QAAQ;QAC9B,SAAS;QACT,0FAA0F;QAC1F,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA,CAAC,CAAC;QACjD,KAAK,KAAK,SAAS,CAAC,MAAM,GAAG,CAAC,CAAA,CAAC,CAAC;KACjC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { HealthCheck } from '../../core/lifecycle/types.js';
|
|
2
|
+
import type { AlertSeverity } from './handle.js';
|
|
3
|
+
/** A condition a source finds true right now. */
|
|
4
|
+
export interface AlertCondition {
|
|
5
|
+
readonly key: string;
|
|
6
|
+
readonly severity: AlertSeverity;
|
|
7
|
+
readonly message: string;
|
|
8
|
+
readonly subject?: {
|
|
9
|
+
tenantId?: string;
|
|
10
|
+
entity?: string;
|
|
11
|
+
entityId?: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Evaluated on every tick. Each returned condition is raised (so an ongoing one groups). When
|
|
16
|
+
* `owns` is given, an open alert the source owns that it no longer returns is resolved.
|
|
17
|
+
*/
|
|
18
|
+
export interface AlertSource {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
owns?(key: string): boolean;
|
|
21
|
+
evaluate(): Promise<AlertCondition[]>;
|
|
22
|
+
}
|
|
23
|
+
interface TableOption {
|
|
24
|
+
readonly table?: string;
|
|
25
|
+
readonly database?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Raises `job-dead-letter:<jobType>` for jobs that exhausted their attempts since the last
|
|
29
|
+
* evaluation (any process: the position is kept in `pipework_alert_source_state`; the first
|
|
30
|
+
* evaluation starts from now, so history is not replayed). The condition clears only by the
|
|
31
|
+
* handle's quiet period, so set `resolveAfterQuietMs` on `alerts.create`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function deadLetterSource(options?: TableOption & {
|
|
34
|
+
severity?: AlertSeverity;
|
|
35
|
+
}): AlertSource;
|
|
36
|
+
/** Raises `job-long-running:<jobType>` while a job of that type has been claimed for longer than `olderThanMs`; resolves when none is. */
|
|
37
|
+
export declare function longRunningSource(options: TableOption & {
|
|
38
|
+
olderThanMs: number;
|
|
39
|
+
severity?: AlertSeverity;
|
|
40
|
+
}): AlertSource;
|
|
41
|
+
/**
|
|
42
|
+
* Raises `queue-backlog:<jobType>` while more than `maxPending` jobs of a type are ready to claim, or the
|
|
43
|
+
* oldest has waited more than `maxOldestAgeMs`; resolves when the type is under both.
|
|
44
|
+
*/
|
|
45
|
+
export declare function backlogSource(options: TableOption & {
|
|
46
|
+
maxPending?: number;
|
|
47
|
+
maxOldestAgeMs?: number;
|
|
48
|
+
severity?: AlertSeverity;
|
|
49
|
+
}): AlertSource;
|
|
50
|
+
/** Raises `health:<name>` while a check reports unhealthy or throws; resolves when it is healthy again. Degraded is not a fault. */
|
|
51
|
+
export declare function healthSource(checks: readonly HealthCheck[], options?: {
|
|
52
|
+
severity?: AlertSeverity;
|
|
53
|
+
}): AlertSource;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/sources.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,iDAAiD;AACjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7E;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,QAAQ,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;CACtC;AAED,UAAU,WAAW;IAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;AAQ7E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,WAAW,GAAG;IAAE,QAAQ,CAAC,EAAE,aAAa,CAAA;CAAO,GAAG,WAAW,CAiCtG;AAED,0IAA0I;AAC1I,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG,WAAW,CAqBvH;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG,WAAW,CA8B5I;AAED,oIAAoI;AACpI,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,aAAa,CAAA;CAAO,GAAG,WAAW,CAqBpH"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { sql } from '../../data/db/sql.js';
|
|
2
|
+
import { pipeSystem } from '../../data/db/db.js';
|
|
3
|
+
import { assertValidIdentifier, quoteIdentifier } from '../../data/db/identifiers.js';
|
|
4
|
+
function jobsTable(table) {
|
|
5
|
+
const name = table ?? 'pipework_jobs';
|
|
6
|
+
assertValidIdentifier(name, 'queue table');
|
|
7
|
+
return quoteIdentifier(name, 'queue table');
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Raises `job-dead-letter:<jobType>` for jobs that exhausted their attempts since the last
|
|
11
|
+
* evaluation (any process: the position is kept in `pipework_alert_source_state`; the first
|
|
12
|
+
* evaluation starts from now, so history is not replayed). The condition clears only by the
|
|
13
|
+
* handle's quiet period, so set `resolveAfterQuietMs` on `alerts.create`.
|
|
14
|
+
*/
|
|
15
|
+
export function deadLetterSource(options = {}) {
|
|
16
|
+
const jobs = jobsTable(options.table);
|
|
17
|
+
const severity = options.severity ?? 'error';
|
|
18
|
+
const name = 'job-dead-letter';
|
|
19
|
+
return {
|
|
20
|
+
name,
|
|
21
|
+
async evaluate() {
|
|
22
|
+
const db = pipeSystem(options.database);
|
|
23
|
+
const first = await db.execute(sql `
|
|
24
|
+
INSERT INTO pipework_alert_source_state (name, cursor_at) VALUES (${name}, clock_timestamp())
|
|
25
|
+
ON CONFLICT (name) DO NOTHING RETURNING name`);
|
|
26
|
+
if (first.length > 0)
|
|
27
|
+
return [];
|
|
28
|
+
const rows = await db.execute(sql `
|
|
29
|
+
WITH cur AS (SELECT cursor_at FROM pipework_alert_source_state WHERE name = ${name} FOR UPDATE),
|
|
30
|
+
found AS (
|
|
31
|
+
SELECT j.job_type, count(*)::int AS n, max(j.completed_at) AS hi,
|
|
32
|
+
(array_agg(j.error_payload->>'message' ORDER BY j.completed_at DESC))[1] AS last_error
|
|
33
|
+
FROM ${sql.raw(jobs)} j, cur
|
|
34
|
+
WHERE j.status = 'dead_letter' AND j.completed_at > cur.cursor_at
|
|
35
|
+
GROUP BY j.job_type),
|
|
36
|
+
moved AS (
|
|
37
|
+
UPDATE pipework_alert_source_state s SET cursor_at = GREATEST(s.cursor_at, (SELECT max(hi) FROM found))
|
|
38
|
+
WHERE s.name = ${name} AND EXISTS (SELECT 1 FROM found) RETURNING 1)
|
|
39
|
+
SELECT job_type, n, last_error, (SELECT count(*) FROM moved) AS moved FROM found ORDER BY job_type`);
|
|
40
|
+
return rows.map(r => ({
|
|
41
|
+
key: `job-dead-letter:${String(r['job_type'])}`,
|
|
42
|
+
severity,
|
|
43
|
+
message: `${String(r['n'])} ${String(r['job_type'])} job(s) dead-lettered`
|
|
44
|
+
+ (r['last_error'] !== null && r['last_error'] !== undefined ? `; last error: ${String(r['last_error'])}` : ''),
|
|
45
|
+
subject: { entity: 'job', entityId: String(r['job_type']) },
|
|
46
|
+
}));
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Raises `job-long-running:<jobType>` while a job of that type has been claimed for longer than `olderThanMs`; resolves when none is. */
|
|
51
|
+
export function longRunningSource(options) {
|
|
52
|
+
const jobs = jobsTable(options.table);
|
|
53
|
+
const severity = options.severity ?? 'warning';
|
|
54
|
+
return {
|
|
55
|
+
name: 'job-long-running',
|
|
56
|
+
owns: key => key.startsWith('job-long-running:'),
|
|
57
|
+
async evaluate() {
|
|
58
|
+
const rows = await pipeSystem(options.database).execute(sql `
|
|
59
|
+
SELECT job_type, count(*)::int AS n, (extract(epoch FROM clock_timestamp() - min(claimed_at)) * 1000)::bigint AS oldest_ms
|
|
60
|
+
FROM ${sql.raw(jobs)}
|
|
61
|
+
WHERE status IN ('claimed', 'running')
|
|
62
|
+
AND claimed_at < clock_timestamp() - ${options.olderThanMs} * interval '1 millisecond'
|
|
63
|
+
GROUP BY job_type ORDER BY job_type`);
|
|
64
|
+
return rows.map(r => ({
|
|
65
|
+
key: `job-long-running:${String(r['job_type'])}`,
|
|
66
|
+
severity,
|
|
67
|
+
message: `${String(r['n'])} ${String(r['job_type'])} job(s) running for more than ${String(options.olderThanMs)} ms (oldest ${String(r['oldest_ms'])} ms)`,
|
|
68
|
+
subject: { entity: 'job', entityId: String(r['job_type']) },
|
|
69
|
+
}));
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Raises `queue-backlog:<jobType>` while more than `maxPending` jobs of a type are ready to claim, or the
|
|
75
|
+
* oldest has waited more than `maxOldestAgeMs`; resolves when the type is under both.
|
|
76
|
+
*/
|
|
77
|
+
export function backlogSource(options) {
|
|
78
|
+
if (options.maxPending === undefined && options.maxOldestAgeMs === undefined) {
|
|
79
|
+
throw new Error('[pipework] alerts.source.backlog needs maxPending, maxOldestAgeMs or both.');
|
|
80
|
+
}
|
|
81
|
+
const jobs = jobsTable(options.table);
|
|
82
|
+
const severity = options.severity ?? 'warning';
|
|
83
|
+
const maxPending = options.maxPending ?? null;
|
|
84
|
+
const maxAge = options.maxOldestAgeMs ?? null;
|
|
85
|
+
return {
|
|
86
|
+
name: 'queue-backlog',
|
|
87
|
+
owns: key => key.startsWith('queue-backlog:'),
|
|
88
|
+
async evaluate() {
|
|
89
|
+
const rows = await pipeSystem(options.database).execute(sql `
|
|
90
|
+
SELECT job_type, n, oldest_ms FROM (
|
|
91
|
+
SELECT job_type, count(*)::int AS n,
|
|
92
|
+
(extract(epoch FROM clock_timestamp() - min(queued_at)) * 1000)::bigint AS oldest_ms
|
|
93
|
+
FROM ${sql.raw(jobs)}
|
|
94
|
+
WHERE status = 'pending' AND (next_retry_at IS NULL OR next_retry_at <= clock_timestamp())
|
|
95
|
+
GROUP BY job_type) p
|
|
96
|
+
WHERE (${maxPending}::int IS NOT NULL AND n > ${maxPending}::int)
|
|
97
|
+
OR (${maxAge}::bigint IS NOT NULL AND oldest_ms > ${maxAge}::bigint)
|
|
98
|
+
ORDER BY job_type`);
|
|
99
|
+
return rows.map(r => ({
|
|
100
|
+
key: `queue-backlog:${String(r['job_type'])}`,
|
|
101
|
+
severity,
|
|
102
|
+
message: `${String(r['n'])} ${String(r['job_type'])} job(s) waiting, the oldest for ${String(r['oldest_ms'])} ms`,
|
|
103
|
+
subject: { entity: 'job', entityId: String(r['job_type']) },
|
|
104
|
+
}));
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** Raises `health:<name>` while a check reports unhealthy or throws; resolves when it is healthy again. Degraded is not a fault. */
|
|
109
|
+
export function healthSource(checks, options = {}) {
|
|
110
|
+
const severity = options.severity ?? 'error';
|
|
111
|
+
const keys = new Set(checks.map(c => `health:${c.name}`));
|
|
112
|
+
return {
|
|
113
|
+
name: 'health',
|
|
114
|
+
owns: key => keys.has(key),
|
|
115
|
+
async evaluate() {
|
|
116
|
+
const found = [];
|
|
117
|
+
for (const check of checks) {
|
|
118
|
+
let message = null;
|
|
119
|
+
try {
|
|
120
|
+
const result = await check.check();
|
|
121
|
+
if (result.status === 'unhealthy')
|
|
122
|
+
message = `${check.name} is unhealthy${result.message !== undefined ? `: ${result.message}` : ''}`;
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
message = `${check.name} check threw: ${err instanceof Error ? err.message : String(err)}`;
|
|
126
|
+
}
|
|
127
|
+
if (message !== null)
|
|
128
|
+
found.push({ key: `health:${check.name}`, severity, message, subject: { entity: 'health', entityId: check.name } });
|
|
129
|
+
}
|
|
130
|
+
return found;
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../src/infra/alerts/sources.ts"],"names":[],"mappings":"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"}
|