Keep the engine's own history, and a screen that reads it
A second bus subscriber folds executions, errors, timings and queue lag into per-minute rollups, keeps failures with their traceback and an audit trail of who published what, and records one row per cascade — manual runs and previews included, under an id of their own that writes no idempotency markers. Read back through /observability/*, which always answers 200 so a degraded engine still renders its own health screen. Also fixes two things found on the way: node-health alerts read `status` where the engine publishes `health`, so a device dropping never alerted anyone, and the Redis queue reported `parked: 0` whatever was held. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017MeiWk3Yq12n2pTvnQWYvt
This commit is contained in:
@@ -379,6 +379,38 @@ export const DashboardsPublicSchema = {
|
||||
title: 'DashboardsPublic'
|
||||
} as const;
|
||||
|
||||
export const DeadLetterSchema = {
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
title: 'Id'
|
||||
},
|
||||
ts: {
|
||||
type: 'number',
|
||||
title: 'Ts'
|
||||
},
|
||||
flow: {
|
||||
type: 'string',
|
||||
title: 'Flow'
|
||||
},
|
||||
node: {
|
||||
type: 'string',
|
||||
title: 'Node'
|
||||
},
|
||||
cause: {
|
||||
type: 'string',
|
||||
title: 'Cause'
|
||||
},
|
||||
reason: {
|
||||
type: 'string',
|
||||
title: 'Reason'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['id', 'ts', 'flow', 'node', 'cause', 'reason'],
|
||||
title: 'DeadLetter'
|
||||
} as const;
|
||||
|
||||
export const EndpointSchema = {
|
||||
properties: {
|
||||
kind: {
|
||||
@@ -426,6 +458,43 @@ these so a value never appears to come from nowhere — or worse, appears to
|
||||
come from whichever node happens to be drawn as a producer.`
|
||||
} as const;
|
||||
|
||||
export const EventRowSchema = {
|
||||
properties: {
|
||||
id: {
|
||||
type: 'integer',
|
||||
title: 'Id'
|
||||
},
|
||||
ts: {
|
||||
type: 'string',
|
||||
format: 'date-time',
|
||||
title: 'Ts'
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
title: 'Type'
|
||||
},
|
||||
flow: {
|
||||
type: 'string',
|
||||
title: 'Flow'
|
||||
},
|
||||
node: {
|
||||
type: 'string',
|
||||
title: 'Node'
|
||||
},
|
||||
detail: {
|
||||
type: 'string',
|
||||
title: 'Detail'
|
||||
},
|
||||
actor: {
|
||||
type: 'string',
|
||||
title: 'Actor'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['id', 'ts', 'type', 'flow', 'node', 'detail', 'actor'],
|
||||
title: 'EventRow'
|
||||
} as const;
|
||||
|
||||
export const FlowDef_InputSchema = {
|
||||
properties: {
|
||||
name: {
|
||||
@@ -597,6 +666,56 @@ export const FlowInput_OutputSchema = {
|
||||
description: 'A message the flow starts with rather than computes.'
|
||||
} as const;
|
||||
|
||||
export const FlowRollupSchema = {
|
||||
properties: {
|
||||
flow: {
|
||||
type: 'string',
|
||||
title: 'Flow'
|
||||
},
|
||||
executions: {
|
||||
type: 'integer',
|
||||
title: 'Executions'
|
||||
},
|
||||
errors: {
|
||||
type: 'integer',
|
||||
title: 'Errors'
|
||||
},
|
||||
messages: {
|
||||
type: 'integer',
|
||||
title: 'Messages'
|
||||
},
|
||||
avg_ms: {
|
||||
type: 'number',
|
||||
title: 'Avg Ms'
|
||||
},
|
||||
avg_lag_ms: {
|
||||
type: 'number',
|
||||
title: 'Avg Lag Ms'
|
||||
},
|
||||
spark: {
|
||||
items: {
|
||||
type: 'integer'
|
||||
},
|
||||
type: 'array',
|
||||
title: 'Spark'
|
||||
},
|
||||
last_error_ts: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Last Error Ts'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['flow', 'executions', 'errors', 'messages', 'avg_ms', 'avg_lag_ms', 'spark'],
|
||||
title: 'FlowRollup'
|
||||
} as const;
|
||||
|
||||
export const FlowStatePublicSchema = {
|
||||
properties: {
|
||||
values: {
|
||||
@@ -698,6 +817,55 @@ export const HTTPValidationErrorSchema = {
|
||||
title: 'HTTPValidationError'
|
||||
} as const;
|
||||
|
||||
export const HealthSummarySchema = {
|
||||
properties: {
|
||||
status: {
|
||||
type: 'string',
|
||||
title: 'Status'
|
||||
},
|
||||
problems: {
|
||||
items: {
|
||||
type: 'string'
|
||||
},
|
||||
type: 'array',
|
||||
title: 'Problems'
|
||||
},
|
||||
flows: {
|
||||
additionalProperties: {
|
||||
type: 'integer'
|
||||
},
|
||||
type: 'object',
|
||||
title: 'Flows'
|
||||
},
|
||||
nodes: {
|
||||
additionalProperties: {
|
||||
type: 'integer'
|
||||
},
|
||||
type: 'object',
|
||||
title: 'Nodes'
|
||||
},
|
||||
queue: {
|
||||
additionalProperties: true,
|
||||
type: 'object',
|
||||
title: 'Queue'
|
||||
},
|
||||
loop_lag: {
|
||||
additionalProperties: {
|
||||
type: 'number'
|
||||
},
|
||||
type: 'object',
|
||||
title: 'Loop Lag'
|
||||
},
|
||||
failures_24h: {
|
||||
type: 'integer',
|
||||
title: 'Failures 24H'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['status', 'problems', 'flows', 'nodes', 'queue', 'loop_lag', 'failures_24h'],
|
||||
title: 'HealthSummary'
|
||||
} as const;
|
||||
|
||||
export const HistoryPointSchema = {
|
||||
properties: {
|
||||
ts: {
|
||||
@@ -1630,6 +1798,63 @@ export const RunRequestSchema = {
|
||||
title: 'RunRequest'
|
||||
} as const;
|
||||
|
||||
export const RunRowSchema = {
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
title: 'Id'
|
||||
},
|
||||
flow: {
|
||||
type: 'string',
|
||||
title: 'Flow'
|
||||
},
|
||||
source: {
|
||||
type: 'string',
|
||||
title: 'Source'
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
title: 'Status'
|
||||
},
|
||||
started_at: {
|
||||
type: 'string',
|
||||
format: 'date-time',
|
||||
title: 'Started At'
|
||||
},
|
||||
finished_at: {
|
||||
anyOf: [
|
||||
{
|
||||
type: 'string',
|
||||
format: 'date-time'
|
||||
},
|
||||
{
|
||||
type: 'null'
|
||||
}
|
||||
],
|
||||
title: 'Finished At'
|
||||
},
|
||||
nodes: {
|
||||
type: 'integer',
|
||||
title: 'Nodes'
|
||||
},
|
||||
errors: {
|
||||
type: 'integer',
|
||||
title: 'Errors'
|
||||
},
|
||||
duration_ms: {
|
||||
type: 'number',
|
||||
title: 'Duration Ms'
|
||||
},
|
||||
deliveries: {
|
||||
type: 'integer',
|
||||
title: 'Deliveries'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['id', 'flow', 'source', 'status', 'started_at', 'nodes', 'errors', 'duration_ms', 'deliveries'],
|
||||
title: 'RunRow'
|
||||
} as const;
|
||||
|
||||
export const SecretNamesSchema = {
|
||||
properties: {
|
||||
data: {
|
||||
@@ -1711,6 +1936,42 @@ export const SectionDef_OutputSchema = {
|
||||
description: 'A grid of widgets under a heading.'
|
||||
} as const;
|
||||
|
||||
export const SeriesPointSchema = {
|
||||
properties: {
|
||||
ts: {
|
||||
type: 'number',
|
||||
title: 'Ts'
|
||||
},
|
||||
executions: {
|
||||
type: 'integer',
|
||||
title: 'Executions'
|
||||
},
|
||||
errors: {
|
||||
type: 'integer',
|
||||
title: 'Errors'
|
||||
},
|
||||
messages: {
|
||||
type: 'integer',
|
||||
title: 'Messages'
|
||||
},
|
||||
avg_ms: {
|
||||
type: 'number',
|
||||
title: 'Avg Ms'
|
||||
},
|
||||
max_ms: {
|
||||
type: 'number',
|
||||
title: 'Max Ms'
|
||||
},
|
||||
avg_lag_ms: {
|
||||
type: 'number',
|
||||
title: 'Avg Lag Ms'
|
||||
}
|
||||
},
|
||||
type: 'object',
|
||||
required: ['ts', 'executions', 'errors', 'messages', 'avg_ms', 'max_ms', 'avg_lag_ms'],
|
||||
title: 'SeriesPoint'
|
||||
} as const;
|
||||
|
||||
export const ShareRequestSchema = {
|
||||
properties: {
|
||||
lib_name: {
|
||||
|
||||
Reference in New Issue
Block a user