@dudousxd/nestjs-durable-dashboard 0.41.0 → 0.42.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/dist/client/durable-client.d.ts +35 -4
- package/dist/client/durable-client.d.ts.map +1 -1
- package/dist/client/durable-client.js +40 -4
- package/dist/client/durable-client.js.map +1 -1
- package/dist/client/run-origin.d.ts +16 -3
- package/dist/client/run-origin.d.ts.map +1 -1
- package/dist/client/run-origin.js +22 -9
- package/dist/client/run-origin.js.map +1 -1
- package/dist/client/summarize-health.d.ts +11 -0
- package/dist/client/summarize-health.d.ts.map +1 -1
- package/dist/client/summarize-health.js +24 -0
- package/dist/client/summarize-health.js.map +1 -1
- package/dist/server/index.cjs +99 -8
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +27 -3
- package/dist/server/index.d.ts +27 -3
- package/dist/server/index.js +99 -8
- package/dist/server/index.js.map +1 -1
- package/dist/spa/assets/bench-nv8gmn-b.js +2 -0
- package/dist/spa/assets/{index-DqmPvOju.js → index-BcYcSsB3.js} +1 -1
- package/dist/spa/assets/index-CTKdGcMe.js +80 -0
- package/dist/spa/assets/{preview-B1H9t8eN.js → preview-GbzTsAP8.js} +1 -1
- package/dist/spa/bench.html +14 -0
- package/dist/spa/index.html +2 -2
- package/dist/spa/preview.html +2 -2
- package/package.json +3 -2
- package/dist/spa/assets/index-Ho8MqZ0t.js +0 -80
package/dist/server/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _dudousxd_nestjs_durable_core from '@dudousxd/nestjs-durable-core';
|
|
2
|
-
import { RunGateway, StateStore, WorkflowEngine, RunQuery, RunListItem, DurableTopology, GroupHealth, RunDetail, RunResult, UpdateResult, EngineEvent, RunStatus } from '@dudousxd/nestjs-durable-core';
|
|
2
|
+
import { RunGateway, StateStore, WorkflowEngine, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, DurableTopology, GroupHealth, RunDetail, RunResult, UpdateResult, EngineEvent, RunStatus } from '@dudousxd/nestjs-durable-core';
|
|
3
3
|
export { RunDetail } from '@dudousxd/nestjs-durable-core';
|
|
4
4
|
import * as rxjs from 'rxjs';
|
|
5
5
|
import { Observable } from 'rxjs';
|
|
@@ -134,6 +134,9 @@ declare class DashboardService {
|
|
|
134
134
|
*/
|
|
135
135
|
metrics(): Promise<string>;
|
|
136
136
|
listRuns(query: RunQuery): Promise<RunListItem[]>;
|
|
137
|
+
/** `(status, origin)` counts over the same predicates {@link listRuns} pages — what keeps the
|
|
138
|
+
* console's chips exact while its list is bounded to a page. */
|
|
139
|
+
runFacets(query: RunFacetQuery): Promise<RunFacetRow[]>;
|
|
137
140
|
/** This deployment's durable role (control plane vs tenant) + tenant name — for the dashboard header
|
|
138
141
|
* badge. Routes through the gateway, which knows its own topology (store-backed = operator, proxy =
|
|
139
142
|
* tenant). Works on both topologies (no store/engine needed). */
|
|
@@ -195,6 +198,18 @@ declare class DashboardService {
|
|
|
195
198
|
}>;
|
|
196
199
|
}
|
|
197
200
|
|
|
201
|
+
/**
|
|
202
|
+
* A run as the CONSOLE'S LIST needs it: every field a row or its derived state reads, and none of the
|
|
203
|
+
* payloads only the detail view opens.
|
|
204
|
+
*
|
|
205
|
+
* `input`, `output` and `error` are dropped. On a real control plane they dominate the response —
|
|
206
|
+
* measured against a 9.5k-run deployment, `error` alone (stack traces on every failed run) was 63% of
|
|
207
|
+
* a 12 MB listing — while no list row, and no `deriveRunState` input, ever reads them. The detail
|
|
208
|
+
* endpoint (`GET runs/:id`) still returns the whole run, which is where those three are actually
|
|
209
|
+
* rendered.
|
|
210
|
+
*/
|
|
211
|
+
type RunListRow = Omit<RunListItem, 'input' | 'output' | 'error'>;
|
|
212
|
+
|
|
198
213
|
/** JSON API consumed by the control-plane SPA. Mounted at `apiBasePath` (set by RouterModule). */
|
|
199
214
|
declare class DurableApiController {
|
|
200
215
|
private readonly dashboard;
|
|
@@ -207,7 +222,16 @@ declare class DurableApiController {
|
|
|
207
222
|
* A blank param (`?namespace=`, from a cleared filter box) is the same as an absent one; passing
|
|
208
223
|
* `''` through would be an exact match on a tenant nobody has, i.e. a silently empty console.
|
|
209
224
|
*/
|
|
210
|
-
runs(status?: RunStatus, workflow?: string, tag?: string, attr?: string | string[], namespace?: string, origin?: string): Promise<
|
|
225
|
+
runs(status?: RunStatus | RunStatus[], workflow?: string, tag?: string, attr?: string | string[], namespace?: string, origin?: string, unattributed?: string, limit?: string, offset?: string): Promise<RunListRow[]>;
|
|
226
|
+
/**
|
|
227
|
+
* `(status, origin)` counts for the runs matching the same tag/tenant/attribute predicates as
|
|
228
|
+
* `GET runs`. This is what lets that listing be PAGED at all: the page bounds what the console
|
|
229
|
+
* renders, this bounds nothing and keeps its status and origin chips exact.
|
|
230
|
+
*
|
|
231
|
+
* `status`, `origin` and the page bounds are deliberately NOT accepted — they are the axes being
|
|
232
|
+
* counted, so narrowing by them would report the answer back to itself.
|
|
233
|
+
*/
|
|
234
|
+
facets(workflow?: string, tag?: string, attr?: string | string[], namespace?: string): Promise<_dudousxd_nestjs_durable_core.RunFacetRow[]>;
|
|
211
235
|
/** Prometheus-text metrics (runs/steps by outcome, per-workflow counts) for a scrape. */
|
|
212
236
|
metrics(): Promise<string>;
|
|
213
237
|
/** Per-group worker health (queue backlog + live worker heartbeats) for the Workers panel. */
|
|
@@ -232,7 +256,7 @@ declare class DurableApiController {
|
|
|
232
256
|
* The filter takes the SAME params as `GET runs` and is parsed identically, so "retry all" acts on
|
|
233
257
|
* exactly the set the operator was looking at rather than a wider one.
|
|
234
258
|
*/
|
|
235
|
-
bulk(action: 'retry' | 'cancel', status?: RunStatus, tag?: string, workflow?: string, attr?: string | string[], compensate?: string, namespace?: string, origin?: string): Promise<{
|
|
259
|
+
bulk(action: 'retry' | 'cancel', status?: RunStatus, tag?: string, workflow?: string, attr?: string | string[], compensate?: string, namespace?: string, origin?: string, unattributed?: string): Promise<{
|
|
236
260
|
matched: number;
|
|
237
261
|
applied: number;
|
|
238
262
|
}>;
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _dudousxd_nestjs_durable_core from '@dudousxd/nestjs-durable-core';
|
|
2
|
-
import { RunGateway, StateStore, WorkflowEngine, RunQuery, RunListItem, DurableTopology, GroupHealth, RunDetail, RunResult, UpdateResult, EngineEvent, RunStatus } from '@dudousxd/nestjs-durable-core';
|
|
2
|
+
import { RunGateway, StateStore, WorkflowEngine, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, DurableTopology, GroupHealth, RunDetail, RunResult, UpdateResult, EngineEvent, RunStatus } from '@dudousxd/nestjs-durable-core';
|
|
3
3
|
export { RunDetail } from '@dudousxd/nestjs-durable-core';
|
|
4
4
|
import * as rxjs from 'rxjs';
|
|
5
5
|
import { Observable } from 'rxjs';
|
|
@@ -134,6 +134,9 @@ declare class DashboardService {
|
|
|
134
134
|
*/
|
|
135
135
|
metrics(): Promise<string>;
|
|
136
136
|
listRuns(query: RunQuery): Promise<RunListItem[]>;
|
|
137
|
+
/** `(status, origin)` counts over the same predicates {@link listRuns} pages — what keeps the
|
|
138
|
+
* console's chips exact while its list is bounded to a page. */
|
|
139
|
+
runFacets(query: RunFacetQuery): Promise<RunFacetRow[]>;
|
|
137
140
|
/** This deployment's durable role (control plane vs tenant) + tenant name — for the dashboard header
|
|
138
141
|
* badge. Routes through the gateway, which knows its own topology (store-backed = operator, proxy =
|
|
139
142
|
* tenant). Works on both topologies (no store/engine needed). */
|
|
@@ -195,6 +198,18 @@ declare class DashboardService {
|
|
|
195
198
|
}>;
|
|
196
199
|
}
|
|
197
200
|
|
|
201
|
+
/**
|
|
202
|
+
* A run as the CONSOLE'S LIST needs it: every field a row or its derived state reads, and none of the
|
|
203
|
+
* payloads only the detail view opens.
|
|
204
|
+
*
|
|
205
|
+
* `input`, `output` and `error` are dropped. On a real control plane they dominate the response —
|
|
206
|
+
* measured against a 9.5k-run deployment, `error` alone (stack traces on every failed run) was 63% of
|
|
207
|
+
* a 12 MB listing — while no list row, and no `deriveRunState` input, ever reads them. The detail
|
|
208
|
+
* endpoint (`GET runs/:id`) still returns the whole run, which is where those three are actually
|
|
209
|
+
* rendered.
|
|
210
|
+
*/
|
|
211
|
+
type RunListRow = Omit<RunListItem, 'input' | 'output' | 'error'>;
|
|
212
|
+
|
|
198
213
|
/** JSON API consumed by the control-plane SPA. Mounted at `apiBasePath` (set by RouterModule). */
|
|
199
214
|
declare class DurableApiController {
|
|
200
215
|
private readonly dashboard;
|
|
@@ -207,7 +222,16 @@ declare class DurableApiController {
|
|
|
207
222
|
* A blank param (`?namespace=`, from a cleared filter box) is the same as an absent one; passing
|
|
208
223
|
* `''` through would be an exact match on a tenant nobody has, i.e. a silently empty console.
|
|
209
224
|
*/
|
|
210
|
-
runs(status?: RunStatus, workflow?: string, tag?: string, attr?: string | string[], namespace?: string, origin?: string): Promise<
|
|
225
|
+
runs(status?: RunStatus | RunStatus[], workflow?: string, tag?: string, attr?: string | string[], namespace?: string, origin?: string, unattributed?: string, limit?: string, offset?: string): Promise<RunListRow[]>;
|
|
226
|
+
/**
|
|
227
|
+
* `(status, origin)` counts for the runs matching the same tag/tenant/attribute predicates as
|
|
228
|
+
* `GET runs`. This is what lets that listing be PAGED at all: the page bounds what the console
|
|
229
|
+
* renders, this bounds nothing and keeps its status and origin chips exact.
|
|
230
|
+
*
|
|
231
|
+
* `status`, `origin` and the page bounds are deliberately NOT accepted — they are the axes being
|
|
232
|
+
* counted, so narrowing by them would report the answer back to itself.
|
|
233
|
+
*/
|
|
234
|
+
facets(workflow?: string, tag?: string, attr?: string | string[], namespace?: string): Promise<_dudousxd_nestjs_durable_core.RunFacetRow[]>;
|
|
211
235
|
/** Prometheus-text metrics (runs/steps by outcome, per-workflow counts) for a scrape. */
|
|
212
236
|
metrics(): Promise<string>;
|
|
213
237
|
/** Per-group worker health (queue backlog + live worker heartbeats) for the Workers panel. */
|
|
@@ -232,7 +256,7 @@ declare class DurableApiController {
|
|
|
232
256
|
* The filter takes the SAME params as `GET runs` and is parsed identically, so "retry all" acts on
|
|
233
257
|
* exactly the set the operator was looking at rather than a wider one.
|
|
234
258
|
*/
|
|
235
|
-
bulk(action: 'retry' | 'cancel', status?: RunStatus, tag?: string, workflow?: string, attr?: string | string[], compensate?: string, namespace?: string, origin?: string): Promise<{
|
|
259
|
+
bulk(action: 'retry' | 'cancel', status?: RunStatus, tag?: string, workflow?: string, attr?: string | string[], compensate?: string, namespace?: string, origin?: string, unattributed?: string): Promise<{
|
|
236
260
|
matched: number;
|
|
237
261
|
applied: number;
|
|
238
262
|
}>;
|
package/dist/server/index.js
CHANGED
|
@@ -101,6 +101,11 @@ var DashboardService = class {
|
|
|
101
101
|
listRuns(query) {
|
|
102
102
|
return this.gateway.listRuns(query);
|
|
103
103
|
}
|
|
104
|
+
/** `(status, origin)` counts over the same predicates {@link listRuns} pages — what keeps the
|
|
105
|
+
* console's chips exact while its list is bounded to a page. */
|
|
106
|
+
runFacets(query) {
|
|
107
|
+
return this.gateway.runFacets(query);
|
|
108
|
+
}
|
|
104
109
|
/** This deployment's durable role (control plane vs tenant) + tenant name — for the dashboard header
|
|
105
110
|
* badge. Routes through the gateway, which knows its own topology (store-backed = operator, proxy =
|
|
106
111
|
* tenant). Works on both topologies (no store/engine needed). */
|
|
@@ -246,6 +251,13 @@ function parseAttrFilters(attr) {
|
|
|
246
251
|
}
|
|
247
252
|
__name(parseAttrFilters, "parseAttrFilters");
|
|
248
253
|
|
|
254
|
+
// src/server/run-list-row.ts
|
|
255
|
+
function toRunListRow(run) {
|
|
256
|
+
const { input: _input, output: _output, error: _error, ...row } = run;
|
|
257
|
+
return row;
|
|
258
|
+
}
|
|
259
|
+
__name(toRunListRow, "toRunListRow");
|
|
260
|
+
|
|
249
261
|
// src/server/durable-api.controller.ts
|
|
250
262
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
251
263
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -264,6 +276,41 @@ function _ts_param2(paramIndex, decorator) {
|
|
|
264
276
|
};
|
|
265
277
|
}
|
|
266
278
|
__name(_ts_param2, "_ts_param");
|
|
279
|
+
function pageBounds(limit, offset) {
|
|
280
|
+
const bound = /* @__PURE__ */ __name((raw) => {
|
|
281
|
+
const n = Number(raw);
|
|
282
|
+
return raw !== void 0 && raw !== "" && Number.isInteger(n) && n >= 0 ? n : void 0;
|
|
283
|
+
}, "bound");
|
|
284
|
+
const l = bound(limit);
|
|
285
|
+
const o = bound(offset);
|
|
286
|
+
return {
|
|
287
|
+
...l !== void 0 ? {
|
|
288
|
+
limit: l
|
|
289
|
+
} : {},
|
|
290
|
+
...o !== void 0 ? {
|
|
291
|
+
offset: o
|
|
292
|
+
} : {}
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
__name(pageBounds, "pageBounds");
|
|
296
|
+
function statusPredicate(status) {
|
|
297
|
+
if (Array.isArray(status)) return status.length ? {
|
|
298
|
+
statuses: status
|
|
299
|
+
} : {};
|
|
300
|
+
return status ? {
|
|
301
|
+
status
|
|
302
|
+
} : {};
|
|
303
|
+
}
|
|
304
|
+
__name(statusPredicate, "statusPredicate");
|
|
305
|
+
function originPredicate(origin, unattributed) {
|
|
306
|
+
if (unattributed === "true" || unattributed === "1") return {
|
|
307
|
+
origin: null
|
|
308
|
+
};
|
|
309
|
+
return origin ? {
|
|
310
|
+
origin
|
|
311
|
+
} : {};
|
|
312
|
+
}
|
|
313
|
+
__name(originPredicate, "originPredicate");
|
|
267
314
|
var DurableApiController = class {
|
|
268
315
|
static {
|
|
269
316
|
__name(this, "DurableApiController");
|
|
@@ -280,14 +327,32 @@ var DurableApiController = class {
|
|
|
280
327
|
* A blank param (`?namespace=`, from a cleared filter box) is the same as an absent one; passing
|
|
281
328
|
* `''` through would be an exact match on a tenant nobody has, i.e. a silently empty console.
|
|
282
329
|
*/
|
|
283
|
-
runs(status, workflow, tag, attr, namespace, origin) {
|
|
284
|
-
|
|
285
|
-
status,
|
|
330
|
+
async runs(status, workflow, tag, attr, namespace, origin, unattributed, limit, offset) {
|
|
331
|
+
const runs = await this.dashboard.listRuns({
|
|
332
|
+
...statusPredicate(status),
|
|
286
333
|
workflow,
|
|
287
334
|
tag,
|
|
288
335
|
attributes: parseAttrFilters(attr),
|
|
289
336
|
namespace: namespace || void 0,
|
|
290
|
-
origin
|
|
337
|
+
...originPredicate(origin, unattributed),
|
|
338
|
+
...pageBounds(limit, offset)
|
|
339
|
+
});
|
|
340
|
+
return runs.map(toRunListRow);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* `(status, origin)` counts for the runs matching the same tag/tenant/attribute predicates as
|
|
344
|
+
* `GET runs`. This is what lets that listing be PAGED at all: the page bounds what the console
|
|
345
|
+
* renders, this bounds nothing and keeps its status and origin chips exact.
|
|
346
|
+
*
|
|
347
|
+
* `status`, `origin` and the page bounds are deliberately NOT accepted — they are the axes being
|
|
348
|
+
* counted, so narrowing by them would report the answer back to itself.
|
|
349
|
+
*/
|
|
350
|
+
facets(workflow, tag, attr, namespace) {
|
|
351
|
+
return this.dashboard.runFacets({
|
|
352
|
+
workflow,
|
|
353
|
+
tag,
|
|
354
|
+
attributes: parseAttrFilters(attr),
|
|
355
|
+
namespace: namespace || void 0
|
|
291
356
|
});
|
|
292
357
|
}
|
|
293
358
|
/** Prometheus-text metrics (runs/steps by outcome, per-workflow counts) for a scrape. */
|
|
@@ -324,14 +389,17 @@ var DurableApiController = class {
|
|
|
324
389
|
* The filter takes the SAME params as `GET runs` and is parsed identically, so "retry all" acts on
|
|
325
390
|
* exactly the set the operator was looking at rather than a wider one.
|
|
326
391
|
*/
|
|
327
|
-
bulk(action, status, tag, workflow, attr, compensate, namespace, origin) {
|
|
392
|
+
bulk(action, status, tag, workflow, attr, compensate, namespace, origin, unattributed) {
|
|
328
393
|
return this.dashboard.bulk(action === "cancel" ? "cancel" : "retry", {
|
|
329
394
|
status,
|
|
330
395
|
tag,
|
|
331
396
|
workflow,
|
|
332
397
|
attributes: parseAttrFilters(attr),
|
|
333
398
|
namespace: namespace || void 0,
|
|
334
|
-
|
|
399
|
+
// The unattributed bucket is a scope a console can actually SELECT, so a bulk action launched
|
|
400
|
+
// under it must be narrowed to it. Dropping the param would widen a retry/cancel to every
|
|
401
|
+
// origin — acting on runs the operator was not looking at.
|
|
402
|
+
...originPredicate(origin, unattributed)
|
|
335
403
|
}, {
|
|
336
404
|
compensate: compensate === "true"
|
|
337
405
|
});
|
|
@@ -382,17 +450,38 @@ _ts_decorate2([
|
|
|
382
450
|
_ts_param2(3, Query("attr")),
|
|
383
451
|
_ts_param2(4, Query("namespace")),
|
|
384
452
|
_ts_param2(5, Query("origin")),
|
|
453
|
+
_ts_param2(6, Query("unattributed")),
|
|
454
|
+
_ts_param2(7, Query("limit")),
|
|
455
|
+
_ts_param2(8, Query("offset")),
|
|
385
456
|
_ts_metadata2("design:type", Function),
|
|
386
457
|
_ts_metadata2("design:paramtypes", [
|
|
387
|
-
|
|
458
|
+
Object,
|
|
388
459
|
String,
|
|
389
460
|
String,
|
|
390
461
|
Object,
|
|
391
462
|
String,
|
|
463
|
+
String,
|
|
464
|
+
String,
|
|
465
|
+
String,
|
|
392
466
|
String
|
|
393
467
|
]),
|
|
394
|
-
_ts_metadata2("design:returntype",
|
|
468
|
+
_ts_metadata2("design:returntype", Promise)
|
|
395
469
|
], DurableApiController.prototype, "runs", null);
|
|
470
|
+
_ts_decorate2([
|
|
471
|
+
Get("runs/facets"),
|
|
472
|
+
_ts_param2(0, Query("workflow")),
|
|
473
|
+
_ts_param2(1, Query("tag")),
|
|
474
|
+
_ts_param2(2, Query("attr")),
|
|
475
|
+
_ts_param2(3, Query("namespace")),
|
|
476
|
+
_ts_metadata2("design:type", Function),
|
|
477
|
+
_ts_metadata2("design:paramtypes", [
|
|
478
|
+
String,
|
|
479
|
+
String,
|
|
480
|
+
Object,
|
|
481
|
+
String
|
|
482
|
+
]),
|
|
483
|
+
_ts_metadata2("design:returntype", void 0)
|
|
484
|
+
], DurableApiController.prototype, "facets", null);
|
|
396
485
|
_ts_decorate2([
|
|
397
486
|
Get("metrics"),
|
|
398
487
|
Header("Content-Type", "text/plain; version=0.0.4"),
|
|
@@ -460,6 +549,7 @@ _ts_decorate2([
|
|
|
460
549
|
_ts_param2(5, Query("compensate")),
|
|
461
550
|
_ts_param2(6, Query("namespace")),
|
|
462
551
|
_ts_param2(7, Query("origin")),
|
|
552
|
+
_ts_param2(8, Query("unattributed")),
|
|
463
553
|
_ts_metadata2("design:type", Function),
|
|
464
554
|
_ts_metadata2("design:paramtypes", [
|
|
465
555
|
String,
|
|
@@ -469,6 +559,7 @@ _ts_decorate2([
|
|
|
469
559
|
Object,
|
|
470
560
|
String,
|
|
471
561
|
String,
|
|
562
|
+
String,
|
|
472
563
|
String
|
|
473
564
|
]),
|
|
474
565
|
_ts_metadata2("design:returntype", void 0)
|