@gadmin2n/schematics 0.0.72 → 0.0.74
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/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/job.prisma +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +0 -21
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +171 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/AgendaJob.ts +60 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeInstance.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeType.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env +5 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +5 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +14 -7
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +49 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +746 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +786 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.controller.ts +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.service.ts +79 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.ts +145 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/{canvas/canvas.service.spec.ts → agendaJob/agendaJob.service.spec.ts} +71 -65
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.service.ts +83 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.module.ts +9 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +100 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +43 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +317 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.controller.ts +16 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.service.ts +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +220 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +82 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +16 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +505 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +22 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.ts +147 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +356 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.ts +110 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.spec.ts +22 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.ts +216 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +356 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +168 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.spec.ts +22 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.ts +199 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.spec.ts +348 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.ts +106 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/yarn.lock +579 -1082
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +278 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/config/development-sql.yaml +5 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/docker-compose.yml +25 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/package.json +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/sql/create-event-trigger.sql +87 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.env +7 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/SANDBOX.md +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package-lock.json +4285 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package.json +28 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/code-execute.test.ts +44 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/http-request.test.ts +87 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/helpers.test.ts +225 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/node-type-consistency.test.ts +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/code-execute.ts +51 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-execute.ts +85 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-query.ts +35 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/http-request.ts +54 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/send-notification.ts +47 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/config.ts +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/condition.ts +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/context.ts +58 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/graph.ts +184 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/helpers.ts +133 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts +57 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/types.ts +77 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +36 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +226 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +411 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/tsconfig.json +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/vitest.config.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/yarn.lock +1905 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/package-lock.json +17555 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +5 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +5 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +63 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +91 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +48 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +43 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +14 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +14 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +309 -56
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/show.tsx +1 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/create.tsx +108 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/edit.tsx +124 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/index.tsx +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +245 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/show.tsx +70 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +0 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +160 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +120 -148
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +74 -181
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/LivePreview.tsx +15 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasConfigRegistry.tsx +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +338 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +18 -17
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/{ChartViewerConfigModal.tsx → MultiChartConfigModal.tsx} +30 -18
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/MultiChartDataSourceModal.tsx +427 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +6 -14
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +10 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/canvasModalProps.ts +24 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +45 -63
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +99 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExportModal.tsx +87 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +322 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ImportModal.tsx +175 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeEditModal.tsx +60 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +1150 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +198 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +81 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +566 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +224 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +524 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +343 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +243 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +363 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/DynamicConfigForm.tsx +154 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +176 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +77 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +112 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +305 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +282 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +469 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +92 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/create.tsx +111 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +127 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/index.tsx +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +254 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +74 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +1501 -1199
- package/package.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.spec.ts +0 -22
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/BarChart/index.tsx +0 -896
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartSwitcher/index.tsx +0 -219
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartViewer/index.tsx +0 -159
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Filter/index.tsx +0 -192
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/LineChart/index.tsx +0 -1034
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/NumCard.module.css +0 -8
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/index.tsx +0 -509
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumLineCard/index.tsx +0 -66
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/PieChart/index.tsx +0 -552
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/RadarChart/index.tsx +0 -263
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Section/index.tsx +0 -35
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Table/index.tsx +0 -207
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/TreemapChart/index.tsx +0 -382
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/WorldMap/index.tsx +0 -135
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/chart-constants.ts +0 -53
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/InfoIcon.tsx +0 -8
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/index.ts +0 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/config.ts +0 -31
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/nameMap.json +0 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/world.geo.json +0 -39349
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/metric-info-tooltip/index.tsx +0 -19
|
@@ -40,6 +40,12 @@ class JobLogsQueryDto {
|
|
|
40
40
|
export class AgendaController {
|
|
41
41
|
constructor(private readonly agendaService: AgendaService) {}
|
|
42
42
|
|
|
43
|
+
@Get('overview')
|
|
44
|
+
@ApiOkResponse({ description: 'Get execution metrics overview (24h/total)' })
|
|
45
|
+
async getOverview() {
|
|
46
|
+
return this.agendaService.getMetricsOverview();
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
@Get('jobs')
|
|
44
50
|
@ApiOkResponse({ description: 'List jobs with overview stats' })
|
|
45
51
|
async getJobs(@Query() query: JobsQueryDto) {
|
|
@@ -267,6 +267,85 @@ export class AgendaService
|
|
|
267
267
|
|
|
268
268
|
// ─── UI management methods ────────────────────────────────────────────────
|
|
269
269
|
|
|
270
|
+
/** 获取执行健康指标概览 */
|
|
271
|
+
async getMetricsOverview() {
|
|
272
|
+
const now = new Date();
|
|
273
|
+
const last24h = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
274
|
+
|
|
275
|
+
const [totalAll, total24h, successAll, success24h, failedAll, failed24h] =
|
|
276
|
+
await Promise.all([
|
|
277
|
+
this.prisma.jobLog.count(),
|
|
278
|
+
this.prisma.jobLog.count({ where: { startAt: { gte: last24h } } }),
|
|
279
|
+
this.prisma.jobLog.count({ where: { status: 'success' } }),
|
|
280
|
+
this.prisma.jobLog.count({
|
|
281
|
+
where: { status: 'success', startAt: { gte: last24h } },
|
|
282
|
+
}),
|
|
283
|
+
this.prisma.jobLog.count({ where: { status: 'failed' } }),
|
|
284
|
+
this.prisma.jobLog.count({
|
|
285
|
+
where: { status: 'failed', startAt: { gte: last24h } },
|
|
286
|
+
}),
|
|
287
|
+
]);
|
|
288
|
+
|
|
289
|
+
// Success rate
|
|
290
|
+
const denomAll = successAll + failedAll;
|
|
291
|
+
const denom24h = success24h + failed24h;
|
|
292
|
+
const successRateAll = denomAll > 0 ? (successAll / denomAll) * 100 : 0;
|
|
293
|
+
const successRate24h = denom24h > 0 ? (success24h / denom24h) * 100 : 0;
|
|
294
|
+
|
|
295
|
+
// Duration AVG/P95 via raw SQL (duration_ms is integer, result in ms)
|
|
296
|
+
const durationAll = await this.prisma.$queryRaw<
|
|
297
|
+
{ avg: number | null; p95: number | null }[]
|
|
298
|
+
>`
|
|
299
|
+
SELECT
|
|
300
|
+
AVG(duration_ms) as avg,
|
|
301
|
+
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration_ms) as p95
|
|
302
|
+
FROM t_job_log
|
|
303
|
+
WHERE status = 'success'
|
|
304
|
+
`;
|
|
305
|
+
|
|
306
|
+
const duration24h = await this.prisma.$queryRaw<
|
|
307
|
+
{ avg: number | null; p95: number | null }[]
|
|
308
|
+
>`
|
|
309
|
+
SELECT
|
|
310
|
+
AVG(duration_ms) as avg,
|
|
311
|
+
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration_ms) as p95
|
|
312
|
+
FROM t_job_log
|
|
313
|
+
WHERE status = 'success' AND start_at >= ${last24h}
|
|
314
|
+
`;
|
|
315
|
+
|
|
316
|
+
// Running/Queued from Agenda queue
|
|
317
|
+
let running = 0;
|
|
318
|
+
let queued = 0;
|
|
319
|
+
if (this.ready) {
|
|
320
|
+
const result = await this.agenda.queryJobs({});
|
|
321
|
+
for (const j of result.jobs) {
|
|
322
|
+
if (j.state === 'running') running++;
|
|
323
|
+
if (j.state === 'queued') queued++;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
totalRuns: { last24h: total24h, total: totalAll },
|
|
329
|
+
successRate: {
|
|
330
|
+
last24h: Math.round(successRate24h * 10) / 10,
|
|
331
|
+
total: Math.round(successRateAll * 10) / 10,
|
|
332
|
+
},
|
|
333
|
+
failed: { last24h: failed24h, total: failedAll },
|
|
334
|
+
duration: {
|
|
335
|
+
last24h: {
|
|
336
|
+
avg: Number(duration24h[0]?.avg) || 0,
|
|
337
|
+
p95: Number(duration24h[0]?.p95) || 0,
|
|
338
|
+
},
|
|
339
|
+
total: {
|
|
340
|
+
avg: Number(durationAll[0]?.avg) || 0,
|
|
341
|
+
p95: Number(durationAll[0]?.p95) || 0,
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
running,
|
|
345
|
+
queued,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
270
349
|
/** 获取任务列表 + 各状态概览 */
|
|
271
350
|
async getJobs(params: GetJobsParams) {
|
|
272
351
|
if (!this.ready) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
|
+
import { AgendaJobController } from './agendaJob.controller';
|
|
3
|
+
import { AgendaJobService } from './agendaJob.service';
|
|
4
|
+
|
|
5
|
+
describe('AgendaJobController', () => {
|
|
6
|
+
let controller: AgendaJobController;
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
10
|
+
controllers: [AgendaJobController],
|
|
11
|
+
providers: [AgendaJobService],
|
|
12
|
+
}).compile();
|
|
13
|
+
|
|
14
|
+
controller = module.get<AgendaJobController>(AgendaJobController);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should be defined', () => {
|
|
18
|
+
expect(controller).toBeDefined();
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ACAttrFilter,
|
|
3
|
+
ACGuard,
|
|
4
|
+
ApiPaginatedResponse,
|
|
5
|
+
PageDto,
|
|
6
|
+
PageMetaDto,
|
|
7
|
+
PageOptionsDto,
|
|
8
|
+
} from '@gadmin2n/nest-common';
|
|
9
|
+
import {
|
|
10
|
+
Body,
|
|
11
|
+
Controller,
|
|
12
|
+
Delete,
|
|
13
|
+
Inject,
|
|
14
|
+
NotFoundException,
|
|
15
|
+
Param,
|
|
16
|
+
ParseUUIDPipe,
|
|
17
|
+
Patch,
|
|
18
|
+
Post,
|
|
19
|
+
UseGuards,
|
|
20
|
+
} from '@nestjs/common';
|
|
21
|
+
import {
|
|
22
|
+
ApiCreatedResponse,
|
|
23
|
+
ApiNotFoundResponse,
|
|
24
|
+
ApiOkResponse,
|
|
25
|
+
ApiTags,
|
|
26
|
+
} from '@nestjs/swagger';
|
|
27
|
+
import { Prisma } from '@prisma/client';
|
|
28
|
+
import { UseRoles } from 'nest-access-control';
|
|
29
|
+
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
|
30
|
+
import { Logger } from 'winston';
|
|
31
|
+
import {
|
|
32
|
+
AgendaJobFindManyArgs,
|
|
33
|
+
AgendaJobWhereSelect,
|
|
34
|
+
EffectedCount,
|
|
35
|
+
UploudResponse,
|
|
36
|
+
} from '../../generated/agendaJob/dto/agendaJob-types.dto';
|
|
37
|
+
import { AgendaJobEntity } from '../../generated/agendaJob/entities/agendaJob.entity';
|
|
38
|
+
import { AgendaJobService } from './agendaJob.service';
|
|
39
|
+
|
|
40
|
+
import { ConfigService } from '@nestjs/config';
|
|
41
|
+
|
|
42
|
+
@UseGuards(ACGuard)
|
|
43
|
+
@Controller('agendaJob')
|
|
44
|
+
@ApiTags('agendaJob')
|
|
45
|
+
export class AgendaJobController {
|
|
46
|
+
constructor(
|
|
47
|
+
private readonly agendaJobService: AgendaJobService,
|
|
48
|
+
private readonly config: ConfigService,
|
|
49
|
+
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
|
50
|
+
) {}
|
|
51
|
+
|
|
52
|
+
@Post('createOne')
|
|
53
|
+
@UseRoles({
|
|
54
|
+
resource: 'agendaJob',
|
|
55
|
+
action: 'create',
|
|
56
|
+
possession: 'any',
|
|
57
|
+
})
|
|
58
|
+
@ApiCreatedResponse({ type: AgendaJobEntity })
|
|
59
|
+
async createOne() {
|
|
60
|
+
// 该资源为只读,创建接口已禁用
|
|
61
|
+
throw new NotFoundException();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Post('findMany')
|
|
65
|
+
@UseRoles({
|
|
66
|
+
resource: 'agendaJob',
|
|
67
|
+
action: 'read',
|
|
68
|
+
possession: 'any',
|
|
69
|
+
})
|
|
70
|
+
@ApiPaginatedResponse(AgendaJobEntity)
|
|
71
|
+
async findMany(
|
|
72
|
+
@Body() body: AgendaJobFindManyArgs,
|
|
73
|
+
@ACAttrFilter() acAttrFilter,
|
|
74
|
+
): Promise<PageDto<AgendaJobEntity>> {
|
|
75
|
+
const { itemCount, entities } = await this.agendaJobService.findMany(
|
|
76
|
+
body as Prisma.AgendaJobFindManyArgs,
|
|
77
|
+
);
|
|
78
|
+
const { skip = 0, take = 10 } = body as Prisma.AgendaJobFindManyArgs;
|
|
79
|
+
const pageOptionsDto: PageOptionsDto = { skip, take };
|
|
80
|
+
const pageMetaDto = new PageMetaDto({ itemCount, pageOptionsDto });
|
|
81
|
+
|
|
82
|
+
return new PageDto(
|
|
83
|
+
entities.map((item) => new AgendaJobEntity(acAttrFilter(item))),
|
|
84
|
+
pageMetaDto,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@Post('/findUnique/:id')
|
|
89
|
+
@UseRoles({
|
|
90
|
+
resource: 'agendaJob',
|
|
91
|
+
action: 'read',
|
|
92
|
+
possession: 'any',
|
|
93
|
+
})
|
|
94
|
+
@ApiOkResponse({ type: AgendaJobEntity })
|
|
95
|
+
@ApiNotFoundResponse({ description: 'Cannot found this record.' })
|
|
96
|
+
async findUnique(
|
|
97
|
+
@Param('id', ParseUUIDPipe) id: string,
|
|
98
|
+
@Body() body: AgendaJobWhereSelect,
|
|
99
|
+
@ACAttrFilter() acAttrFilter,
|
|
100
|
+
) {
|
|
101
|
+
const item = await this.agendaJobService.findUnique(id, body);
|
|
102
|
+
if (!item) {
|
|
103
|
+
throw new NotFoundException();
|
|
104
|
+
}
|
|
105
|
+
return new AgendaJobEntity(acAttrFilter(item));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Patch('updateUnique/:id')
|
|
109
|
+
@UseRoles({
|
|
110
|
+
resource: 'agendaJob',
|
|
111
|
+
action: 'update',
|
|
112
|
+
possession: 'any',
|
|
113
|
+
})
|
|
114
|
+
@ApiOkResponse({ type: AgendaJobEntity })
|
|
115
|
+
@ApiNotFoundResponse({ description: 'Cannot found this record.' })
|
|
116
|
+
async updateUnique() {
|
|
117
|
+
// 该资源为只读,更新接口已禁用
|
|
118
|
+
throw new NotFoundException();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@Delete('deleteUnique/:id')
|
|
122
|
+
@UseRoles({
|
|
123
|
+
resource: 'agendaJob',
|
|
124
|
+
action: 'delete',
|
|
125
|
+
possession: 'any',
|
|
126
|
+
})
|
|
127
|
+
@ApiOkResponse({ type: EffectedCount })
|
|
128
|
+
@ApiNotFoundResponse({ description: 'Cannot found this record.' })
|
|
129
|
+
async deleteUnique() {
|
|
130
|
+
// 该资源为只读,删除接口已禁用
|
|
131
|
+
throw new NotFoundException();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@Post('upload')
|
|
135
|
+
@UseRoles({
|
|
136
|
+
resource: 'agendaJob',
|
|
137
|
+
action: 'create',
|
|
138
|
+
possession: 'any',
|
|
139
|
+
})
|
|
140
|
+
@ApiCreatedResponse({ type: UploudResponse })
|
|
141
|
+
async uploadFile() {
|
|
142
|
+
// 该资源为只读,上传接口已禁用
|
|
143
|
+
throw new NotFoundException();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { AgendaJobController } from './agendaJob.controller';
|
|
3
|
+
import { AgendaJobService } from './agendaJob.service';
|
|
4
|
+
|
|
5
|
+
@Module({
|
|
6
|
+
controllers: [AgendaJobController],
|
|
7
|
+
providers: [AgendaJobService],
|
|
8
|
+
exports: [AgendaJobService],
|
|
9
|
+
})
|
|
10
|
+
export class AgendaJobModule {}
|
|
@@ -9,11 +9,11 @@ jest.mock('nestjs-prisma', () => ({
|
|
|
9
9
|
}));
|
|
10
10
|
|
|
11
11
|
import { PrismaService } from 'nestjs-prisma';
|
|
12
|
-
import {
|
|
12
|
+
import { AgendaJobService } from './agendaJob.service';
|
|
13
13
|
|
|
14
14
|
// Mock PrismaService
|
|
15
15
|
const mockPrismaService = {
|
|
16
|
-
|
|
16
|
+
agendaJob: {
|
|
17
17
|
create: jest.fn(),
|
|
18
18
|
createMany: jest.fn(),
|
|
19
19
|
findMany: jest.fn(),
|
|
@@ -42,8 +42,8 @@ const mockConfigService = {
|
|
|
42
42
|
get: jest.fn(),
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
describe('
|
|
46
|
-
let service:
|
|
45
|
+
describe('AgendaJobService', () => {
|
|
46
|
+
let service: AgendaJobService;
|
|
47
47
|
let prisma: typeof mockPrismaService;
|
|
48
48
|
|
|
49
49
|
beforeEach(async () => {
|
|
@@ -52,14 +52,14 @@ describe('CanvasService', () => {
|
|
|
52
52
|
|
|
53
53
|
const module: TestingModule = await Test.createTestingModule({
|
|
54
54
|
providers: [
|
|
55
|
-
|
|
55
|
+
AgendaJobService,
|
|
56
56
|
{ provide: PrismaService, useValue: mockPrismaService },
|
|
57
57
|
{ provide: ConfigService, useValue: mockConfigService },
|
|
58
58
|
{ provide: WINSTON_MODULE_PROVIDER, useValue: mockLogger },
|
|
59
59
|
],
|
|
60
60
|
}).compile();
|
|
61
61
|
|
|
62
|
-
service = module.get<
|
|
62
|
+
service = module.get<AgendaJobService>(AgendaJobService);
|
|
63
63
|
prisma = mockPrismaService;
|
|
64
64
|
});
|
|
65
65
|
|
|
@@ -68,23 +68,24 @@ describe('CanvasService', () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
describe('createOne', () => {
|
|
71
|
-
it('should create a single
|
|
71
|
+
it('should create a single agendaJob record', async () => {
|
|
72
72
|
const createArgs = {
|
|
73
73
|
data: {
|
|
74
74
|
name: 'test_name',
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
priority: 0,
|
|
76
|
+
nextRunAt: new Date(),
|
|
77
|
+
type: 'normal',
|
|
78
|
+
lockedAt: new Date(),
|
|
78
79
|
},
|
|
79
80
|
};
|
|
80
81
|
const expectedResult = { id: 'test-id-123', ...createArgs.data };
|
|
81
82
|
|
|
82
|
-
prisma.
|
|
83
|
+
prisma.agendaJob.create.mockResolvedValue(expectedResult);
|
|
83
84
|
|
|
84
85
|
const result = await service.createOne(createArgs);
|
|
85
86
|
|
|
86
|
-
expect(prisma.
|
|
87
|
-
expect(prisma.
|
|
87
|
+
expect(prisma.agendaJob.create).toHaveBeenCalledWith(createArgs);
|
|
88
|
+
expect(prisma.agendaJob.create).toHaveBeenCalledTimes(1);
|
|
88
89
|
expect(result).toEqual(expectedResult);
|
|
89
90
|
});
|
|
90
91
|
|
|
@@ -92,14 +93,15 @@ describe('CanvasService', () => {
|
|
|
92
93
|
const createArgs = {
|
|
93
94
|
data: {
|
|
94
95
|
name: 'test_name',
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
priority: 0,
|
|
97
|
+
nextRunAt: new Date(),
|
|
98
|
+
type: 'normal',
|
|
99
|
+
lockedAt: new Date(),
|
|
98
100
|
},
|
|
99
101
|
};
|
|
100
102
|
const error = new Error('Database connection failed');
|
|
101
103
|
|
|
102
|
-
prisma.
|
|
104
|
+
prisma.agendaJob.create.mockRejectedValue(error);
|
|
103
105
|
|
|
104
106
|
await expect(service.createOne(createArgs)).rejects.toThrow(
|
|
105
107
|
'Database connection failed',
|
|
@@ -108,28 +110,30 @@ describe('CanvasService', () => {
|
|
|
108
110
|
});
|
|
109
111
|
|
|
110
112
|
describe('createMany', () => {
|
|
111
|
-
it('should create multiple
|
|
113
|
+
it('should create multiple agendaJob records with skipDuplicates', async () => {
|
|
112
114
|
const data = [
|
|
113
115
|
{
|
|
114
116
|
name: 'test_name',
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
priority: 0,
|
|
118
|
+
nextRunAt: new Date(),
|
|
119
|
+
type: 'normal',
|
|
120
|
+
lockedAt: new Date(),
|
|
118
121
|
},
|
|
119
122
|
{
|
|
120
123
|
name: 'test_name',
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
priority: 0,
|
|
125
|
+
nextRunAt: new Date(),
|
|
126
|
+
type: 'normal',
|
|
127
|
+
lockedAt: new Date(),
|
|
124
128
|
},
|
|
125
129
|
];
|
|
126
130
|
const expectedResult = { count: 2 };
|
|
127
131
|
|
|
128
|
-
prisma.
|
|
132
|
+
prisma.agendaJob.createMany.mockResolvedValue(expectedResult);
|
|
129
133
|
|
|
130
134
|
const result = await service.createMany(data);
|
|
131
135
|
|
|
132
|
-
expect(prisma.
|
|
136
|
+
expect(prisma.agendaJob.createMany).toHaveBeenCalledWith({
|
|
133
137
|
data,
|
|
134
138
|
skipDuplicates: true,
|
|
135
139
|
});
|
|
@@ -146,15 +150,15 @@ describe('CanvasService', () => {
|
|
|
146
150
|
};
|
|
147
151
|
const mockEntities = [{ id: 'test-id-123' }, { id: 'test-id-123' }];
|
|
148
152
|
|
|
149
|
-
prisma.
|
|
150
|
-
prisma.
|
|
153
|
+
prisma.agendaJob.count.mockResolvedValue(2);
|
|
154
|
+
prisma.agendaJob.findMany.mockResolvedValue(mockEntities);
|
|
151
155
|
|
|
152
156
|
const result = await service.findMany(findArgs);
|
|
153
157
|
|
|
154
|
-
expect(prisma.
|
|
158
|
+
expect(prisma.agendaJob.count).toHaveBeenCalledWith({
|
|
155
159
|
where: findArgs.where,
|
|
156
160
|
});
|
|
157
|
-
expect(prisma.
|
|
161
|
+
expect(prisma.agendaJob.findMany).toHaveBeenCalledWith(findArgs);
|
|
158
162
|
expect(result).toEqual({
|
|
159
163
|
itemCount: 2,
|
|
160
164
|
entities: mockEntities,
|
|
@@ -164,8 +168,8 @@ describe('CanvasService', () => {
|
|
|
164
168
|
it('should return empty result when no records found', async () => {
|
|
165
169
|
const findArgs = { where: {} };
|
|
166
170
|
|
|
167
|
-
prisma.
|
|
168
|
-
prisma.
|
|
171
|
+
prisma.agendaJob.count.mockResolvedValue(0);
|
|
172
|
+
prisma.agendaJob.findMany.mockResolvedValue([]);
|
|
169
173
|
|
|
170
174
|
const result = await service.findMany(findArgs);
|
|
171
175
|
|
|
@@ -174,16 +178,16 @@ describe('CanvasService', () => {
|
|
|
174
178
|
});
|
|
175
179
|
|
|
176
180
|
describe('findUnique', () => {
|
|
177
|
-
it('should find a single
|
|
181
|
+
it('should find a single agendaJob record by id', async () => {
|
|
178
182
|
const id = 'test-id-123';
|
|
179
183
|
const select = { id: true };
|
|
180
184
|
const expectedResult = { id: 'test-id-123' };
|
|
181
185
|
|
|
182
|
-
prisma.
|
|
186
|
+
prisma.agendaJob.findUnique.mockResolvedValue(expectedResult);
|
|
183
187
|
|
|
184
188
|
const result = await service.findUnique(id, select);
|
|
185
189
|
|
|
186
|
-
expect(prisma.
|
|
190
|
+
expect(prisma.agendaJob.findUnique).toHaveBeenCalledWith({
|
|
187
191
|
where: { id },
|
|
188
192
|
select,
|
|
189
193
|
});
|
|
@@ -191,7 +195,7 @@ describe('CanvasService', () => {
|
|
|
191
195
|
});
|
|
192
196
|
|
|
193
197
|
it('should return null when record not found', async () => {
|
|
194
|
-
prisma.
|
|
198
|
+
prisma.agendaJob.findUnique.mockResolvedValue(null);
|
|
195
199
|
|
|
196
200
|
const result = await service.findUnique('test-id-123', { id: true });
|
|
197
201
|
|
|
@@ -200,21 +204,22 @@ describe('CanvasService', () => {
|
|
|
200
204
|
});
|
|
201
205
|
|
|
202
206
|
describe('updateUnique', () => {
|
|
203
|
-
it('should update a single
|
|
207
|
+
it('should update a single agendaJob record', async () => {
|
|
204
208
|
const id = 'test-id-123';
|
|
205
209
|
const data = {
|
|
206
210
|
name: 'test_name',
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
priority: 0,
|
|
212
|
+
nextRunAt: new Date(),
|
|
213
|
+
type: 'normal',
|
|
214
|
+
lockedAt: new Date(),
|
|
210
215
|
};
|
|
211
216
|
const expectedResult = { id: 'test-id-123', ...data };
|
|
212
217
|
|
|
213
|
-
prisma.
|
|
218
|
+
prisma.agendaJob.update.mockResolvedValue(expectedResult);
|
|
214
219
|
|
|
215
220
|
const result = await service.updateUnique(id, data);
|
|
216
221
|
|
|
217
|
-
expect(prisma.
|
|
222
|
+
expect(prisma.agendaJob.update).toHaveBeenCalledWith({
|
|
218
223
|
where: { id },
|
|
219
224
|
data,
|
|
220
225
|
});
|
|
@@ -223,95 +228,96 @@ describe('CanvasService', () => {
|
|
|
223
228
|
});
|
|
224
229
|
|
|
225
230
|
describe('updateMany', () => {
|
|
226
|
-
it('should update multiple
|
|
231
|
+
it('should update multiple agendaJob records', async () => {
|
|
227
232
|
const updateArgs = {
|
|
228
233
|
where: {},
|
|
229
234
|
data: {
|
|
230
235
|
name: 'test_name',
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
236
|
+
priority: 0,
|
|
237
|
+
nextRunAt: new Date(),
|
|
238
|
+
type: 'normal',
|
|
239
|
+
lockedAt: new Date(),
|
|
234
240
|
},
|
|
235
241
|
};
|
|
236
242
|
const expectedResult = { count: 5 };
|
|
237
243
|
|
|
238
|
-
prisma.
|
|
244
|
+
prisma.agendaJob.updateMany.mockResolvedValue(expectedResult);
|
|
239
245
|
|
|
240
246
|
const result = await service.updateMany(updateArgs);
|
|
241
247
|
|
|
242
|
-
expect(prisma.
|
|
248
|
+
expect(prisma.agendaJob.updateMany).toHaveBeenCalledWith(updateArgs);
|
|
243
249
|
expect(result).toEqual(expectedResult);
|
|
244
250
|
});
|
|
245
251
|
});
|
|
246
252
|
|
|
247
253
|
describe('deleteUnique', () => {
|
|
248
|
-
it('should delete a single
|
|
254
|
+
it('should delete a single agendaJob record and return count', async () => {
|
|
249
255
|
const id = 'test-id-123';
|
|
250
256
|
|
|
251
|
-
prisma.
|
|
257
|
+
prisma.agendaJob.delete.mockResolvedValue({ id: 'test-id-123' });
|
|
252
258
|
|
|
253
259
|
const result = await service.deleteUnique(id);
|
|
254
260
|
|
|
255
|
-
expect(prisma.
|
|
261
|
+
expect(prisma.agendaJob.delete).toHaveBeenCalledWith({ where: { id } });
|
|
256
262
|
expect(result).toEqual({ count: 1 });
|
|
257
263
|
});
|
|
258
264
|
});
|
|
259
265
|
|
|
260
266
|
describe('deleteMany', () => {
|
|
261
|
-
it('should delete multiple
|
|
267
|
+
it('should delete multiple agendaJob records', async () => {
|
|
262
268
|
const deleteArgs = { where: {} };
|
|
263
269
|
const expectedResult = { count: 3 };
|
|
264
270
|
|
|
265
|
-
prisma.
|
|
271
|
+
prisma.agendaJob.deleteMany.mockResolvedValue(expectedResult);
|
|
266
272
|
|
|
267
273
|
const result = await service.deleteMany(deleteArgs);
|
|
268
274
|
|
|
269
|
-
expect(prisma.
|
|
275
|
+
expect(prisma.agendaJob.deleteMany).toHaveBeenCalledWith(deleteArgs);
|
|
270
276
|
expect(result).toEqual(expectedResult);
|
|
271
277
|
});
|
|
272
278
|
});
|
|
273
279
|
|
|
274
280
|
describe('count', () => {
|
|
275
|
-
it('should count
|
|
281
|
+
it('should count agendaJob records with filter', async () => {
|
|
276
282
|
const countArgs = { where: {} };
|
|
277
283
|
|
|
278
|
-
prisma.
|
|
284
|
+
prisma.agendaJob.count.mockResolvedValue(10);
|
|
279
285
|
|
|
280
286
|
const result = await service.count(countArgs);
|
|
281
287
|
|
|
282
|
-
expect(prisma.
|
|
288
|
+
expect(prisma.agendaJob.count).toHaveBeenCalledWith(countArgs);
|
|
283
289
|
expect(result).toBe(10);
|
|
284
290
|
});
|
|
285
291
|
|
|
286
292
|
it('should count all records when no filter provided', async () => {
|
|
287
|
-
prisma.
|
|
293
|
+
prisma.agendaJob.count.mockResolvedValue(100);
|
|
288
294
|
|
|
289
295
|
const result = await service.count();
|
|
290
296
|
|
|
291
|
-
expect(prisma.
|
|
297
|
+
expect(prisma.agendaJob.count).toHaveBeenCalledWith(undefined);
|
|
292
298
|
expect(result).toBe(100);
|
|
293
299
|
});
|
|
294
300
|
});
|
|
295
301
|
|
|
296
302
|
describe('groupBy', () => {
|
|
297
|
-
it('should group
|
|
303
|
+
it('should group agendaJob records by specified field', async () => {
|
|
298
304
|
const groupByArgs = {
|
|
299
305
|
by: ['id'],
|
|
300
306
|
_count: { id: true },
|
|
301
307
|
};
|
|
302
308
|
const expectedResult = [{ id: 'test-id-123', _count: { id: 50 } }];
|
|
303
309
|
|
|
304
|
-
prisma.
|
|
310
|
+
prisma.agendaJob.groupBy.mockResolvedValue(expectedResult);
|
|
305
311
|
|
|
306
312
|
const result = await service.groupBy(groupByArgs as any);
|
|
307
313
|
|
|
308
|
-
expect(prisma.
|
|
314
|
+
expect(prisma.agendaJob.groupBy).toHaveBeenCalledWith(groupByArgs);
|
|
309
315
|
expect(result).toEqual(expectedResult);
|
|
310
316
|
});
|
|
311
317
|
});
|
|
312
318
|
|
|
313
319
|
describe('aggregate', () => {
|
|
314
|
-
it('should aggregate
|
|
320
|
+
it('should aggregate agendaJob records', async () => {
|
|
315
321
|
const aggregateArgs = {
|
|
316
322
|
_count: true,
|
|
317
323
|
_max: { id: true },
|
|
@@ -323,11 +329,11 @@ describe('CanvasService', () => {
|
|
|
323
329
|
_min: { id: 'test-id-123' },
|
|
324
330
|
};
|
|
325
331
|
|
|
326
|
-
prisma.
|
|
332
|
+
prisma.agendaJob.aggregate.mockResolvedValue(expectedResult);
|
|
327
333
|
|
|
328
334
|
const result = await service.aggregate(aggregateArgs);
|
|
329
335
|
|
|
330
|
-
expect(prisma.
|
|
336
|
+
expect(prisma.agendaJob.aggregate).toHaveBeenCalledWith(aggregateArgs);
|
|
331
337
|
expect(result).toEqual(expectedResult);
|
|
332
338
|
});
|
|
333
339
|
});
|