feat(scenario): add scheduler, cancelled step status, and runs list endpoint

- install @nestjs/schedule and register ScheduleModule in AppModule
- add ScenarioSchedulerService with two 1s interval jobs:
  - activatePendingRuns: flips pending runs to in_progress
  - processPendingStepRuns: executes next pending step run (login or exec),
    runs optional validateCode, advances or fails the run accordingly
- on step pass: next waiting step becomes pending; last step pass flips run to pass
- on step fail: remaining steps set to cancelled, run flipped to fail
- add cancelled to RunStepStatus union
- add GET /scenarios/:id/runs with pagination and optional ?status= filter
This commit is contained in:
2026-04-07 14:51:37 +03:00
parent caf120741d
commit cff36ffeff
9 changed files with 355 additions and 4 deletions
+12
View File
@@ -17,6 +17,7 @@ import { UpdateScenarioDto } from './dto/update-scenario.dto';
import { CreateScenarioStepDto } from './dto/create-scenario-step.dto';
import { UpdateScenarioStepDto } from './dto/update-scenario-step.dto';
import { PaginationQueryDto } from './dto/pagination-query.dto';
import { RunsQueryDto } from './dto/runs-query.dto';
@ApiTags('scenarios')
@Controller('scenarios')
@@ -114,6 +115,17 @@ export class ScenarioController {
// ── Runs ──────────────────────────────────────────────────────────────────
@Get(':id/runs')
@ApiOperation({ summary: 'List runs for a scenario (paginated, filterable by status)' })
@ApiResponse({ status: 200 })
@ApiResponse({ status: 404, description: 'Scenario not found' })
findRuns(
@Param('id', ParseIntPipe) id: number,
@Query() query: RunsQueryDto,
) {
return this.scenarioService.findRuns(id, query);
}
@Post(':id/run')
@ApiOperation({ summary: 'Create a new run for a scenario' })
@ApiResponse({ status: 201, description: 'Run created with step runs' })