# Changelog

## 1.9.5

### Added
- Added `runScheduledTasksRegistrar` to `TasksQueueModule.forRootAsync(...)` so NestJS `@ScheduledTask(...)` auto-discovery and bootstrap provisioning can be disabled per module instance.
- Added unit coverage for default and disabled scheduled-task registrar wiring.

### Changed
- Updated README and NestJS scheduled-task documentation to describe disabling `ScheduledTasksRegistrar`, with test-focused guidance.

## 1.9.1

### Added
- Added `isPeriodic` filtering to `ManageTasksQueueService.findByParameters(...)`.
- Added date-field sorting options for management task search results.
- Added last heartbeat to management task DTOs and search sorting.
- Added task id sorting for management task search results.
- Added integration coverage for periodic filtering and management search sorting.

## 1.9.0

### Added
- Added pool runtime metrics for registered queue labels, slot usage, and polling loop health.
- Added per-queue polling, fetch, and task lifecycle counters.
- Added unit coverage for runtime metrics emitted through `application-metrics`.

## 1.8.0

### Added
- Added `ManageTasksQueueService.findChildrenTree(...)` for loading all direct and nested child tasks of a root task.
- Added PostgreSQL integration coverage that verifies child tree lookup returns only descendants of the requested root and excludes unrelated branches.

## 1.7.9

### Added
- Added `ManagedWorkflowTask` as a policy-oriented orchestration base class on top of `MultiStepTask`.
- Added constructor-only `maxRuns` configuration for managed workflows.
- Added integration coverage for managed workflow scenarios: happy path, invalid run actions, child terminal failure, allow-failure continuation, invalid `runCount`, and `maxRuns` boundaries.
- Added unit coverage for `maxRuns` defaults and constructor validation rules.
- Added dedicated documentation for managed workflows in `docs/managed-workflow-task.md`.

### Changed
- Changed managed workflow `maxRuns` validation to require a positive integer.
- Changed managed workflow `runCount` validation to require a non-negative integer with explicit failure on invalid payload state.
- Updated README and multi-step workflow docs to include `ManagedWorkflowTask` and reflect current orchestration semantics.

## 1.7.8

### Added
- Added declarative NestJS method-level worker registration with `@Worker({ queue, pool? })`.
- Added automatic discovery and registration of decorated provider methods through Nest `DiscoveryModule`.
- Added declarative periodic task provisioning in NestJS providers via `@ScheduledTask(...)` with cron, fixed-rate, and fixed-delay variants.
- Added `replaceExisting` support for periodic scheduling APIs and DAO persistence flow.
- Added unit coverage for decorated worker discovery and runtime method invocation adapter behavior.
- Added unit coverage for scheduled task discovery and periodic replacement conflict handling.
- Added documentation for the new decorator-based registration flow in `README.md` and `docs/nest-worker-decorator.md`.
- Added documentation for `@ScheduledTask(...)` and `replaceExisting` behavior in `README.md` and `docs/nest-scheduled-task-decorator.md`.

### Changed
- `TasksQueueModule` now wires discovery registrars that register decorated methods before pool startup while preserving existing `TasksPoolsService.registerWorker(...)` semantics.
- `@ScheduledTask(...)` now auto-registers the decorated method as the queue worker and supports optional `pool` selection.
- `@ScheduledTask(...)` worker registration now runs on module init, while schedule provisioning runs on application bootstrap to avoid early schema access.
- Combining `@ScheduledTask(...)` and `@Worker(...)` on the same method now throws an initialization error.

## 1.7.6

### Fixed
- Fixed `SequentialTask` auto-continue semantics so steps that run after an intermediate local step do not retain stale `resolvedChildTask` from an earlier child completion.
- Fixed `TasksPoolsService.stop()` to clear its shutdown timeout timer after successful stop, preventing Jest open-handle warnings in test runs.

### Added
- Added unit coverage that verifies auto-continued sequential steps receive updated payload while stale child references are cleared.
- Added unit coverage for shutdown timeout cleanup in `TasksPoolsService.stop()`.

## 1.7.5

### Fixed
- Fixed cross-pool parent-child notifications so child tasks scheduled into another pool start immediately instead of waiting for that pool's next polling interval.
- Fixed blocked parent wake-up notifications so parents resume immediately even when the completed child ran in a different pool.

### Added
- Added unit coverage for cross-pool queue notification dispatch in `TasksQueueWorker`.
- Added an integration test that reproduces cross-pool parent-child execution with `loopInterval = 1 minute` and verifies prompt child start and parent wake-up.
- Added unit and integration coverage for `SequentialTask` flows that contain intermediate steps without `spawnChild(...)`, including database assertions for persisted parent payload and final result.

### Changed
- Changed `SequentialTask` so a step that finishes without `context.spawnChild(...)` automatically advances to the next configured step in the same parent execution.
- Updated README and multi-step workflow documentation to describe mixed sequential flows such as `child -> local step -> child`.

## 1.7.4

### Added
- Added a real PostgreSQL integration test harness based on `testcontainers`.
- Added integration coverage for task execution lifecycle, parent-child workflows, stalled-task handling, periodic scheduling, lifecycle callbacks, management APIs, DAO cleanup flows, and ownership race scenarios.
- Added broader public API JSDoc across queue services, models, scheduling APIs, and NestJS integration types.

### Changed
- Hardened task ownership checks so stale attempts cannot heartbeat, finish, fail, block, or wake tasks after ownership has moved to a newer attempt.
- Refined `SequentialTask` payload handling and expanded workflow-specific coverage around parent-child continuations.
- Enabled coverage reporting for the integration suite and aligned the repository with the new ESLint ruleset.
- Expanded README and detailed documentation for heartbeat behavior, multi-step workflows, and operational usage.

## 1.7.3

### Fixed
- Fixed terminal failure persistence so submitted `result` is retained for terminal task failures instead of being cleared incorrectly.

## 1.7.2

### Changed
- Improved `MultiStepPayload` ergonomics for parent-child workflows.
- Refined `SequentialTask` continuation behavior and expanded related workflow coverage and documentation.

## 1.7.1

### Changed
- Prevented deletion of finished tasks while any ancestor in the parent chain is still unfinished.

## 1.7.0

### Added
- Added optional `result jsonb` column to `tasks_queue` for explicit final task output persistence.
- Added `TaskContext.submitResult(...)` for workers to submit final task output independently from `setPayload(...)`.

### Changed
- `TaskStateSnapshot` and management task views now expose optional `result`.
- Parent-child orchestration now reads child output from `childTask.result` instead of overloading `childTask.payload`.
- Runtime persistence keeps `payload` as task input/runtime state and stores `result` only on completed runs or terminal failures.

### Migration
Apply the following SQL to existing databases:

```sql
ALTER TABLE tasks_queue
    ADD COLUMN IF NOT EXISTS result jsonb DEFAULT NULL;

COMMENT ON COLUMN tasks_queue.result IS
    'The optional final result submitted by the worker after task completion';
```

## 1.6.0

### Added
- Added `ActiveChildState` and `MultiStepPayload.activeChild` to persist active child orchestration metadata.
- Added optional `allowFailure` flag to `TaskContext.spawnChild(...)` child scheduling details so parent workflows can continue from `childFailed(...)` without masking child `error` status.

### Changed
- `MultiStepTask.childFinished(...)` and `MultiStepTask.childFailed(...)` now receive `activeChild` metadata, and `childFailed(...)` also receives `context` for continuation flows.
- `TaskContext` now exposes `resolvedChildTask` as `Option<TaskStateSnapshot>` during parent continuation after child resolution.
- `MultiStepPayload.fromJson(...)` now reads both the new `activeChild` structure and legacy `activeChildId` payloads for backward compatibility.

## 1.5.0

### Added
- Added support for parent-child task relations with `parent_id`.
- Added `blocked` task status for multi-step orchestration flows.
- Added `TaskContext.spawnChild(...)` for declarative child task scheduling from a parent task.
- Added `TaskContext.taskId`, `TaskContext.setPayload(...)`, and `TaskContext.findTask(...)` for workflow-aware task execution.
- Added `TaskContext.ping()` and persistent task heartbeats for long-running workers.
- Added `MultiStepPayload` with separate `workflowPayload`, `userPayload`, and `activeChildId`.
- Added `MultiStepTask` for custom state-machine workflows with one active child at a time.
- Added `SequentialTask` for happy-path sequential workflows that either complete all configured steps or fail.

### Changed
- Parent tasks are now automatically moved to `blocked` after successful child scheduling and woken up only when the child reaches a terminal state.
- Stalled child tasks now wake blocked parents when they end in terminal `error`.
- Stalled task detection now uses the latest heartbeat when available instead of relying only on `started`.

### Migration
Apply the following SQL to existing databases:

```sql
ALTER TABLE tasks_queue
    ADD COLUMN IF NOT EXISTS parent_id int4 DEFAULT NULL
        REFERENCES tasks_queue (id) ON DELETE SET NULL;

ALTER TABLE tasks_queue
    ADD COLUMN IF NOT EXISTS last_heartbeat timestamp DEFAULT NULL;

ALTER TABLE tasks_queue
    DROP CONSTRAINT IF EXISTS tasks_queue_status_check;

ALTER TABLE tasks_queue
    ADD CONSTRAINT tasks_queue_status_check
        CHECK (status IN ('pending', 'in_progress', 'blocked', 'finished', 'error'));

CREATE INDEX IF NOT EXISTS tasks_queue_parent_id_idx
    ON tasks_queue (parent_id);
```

## 1.4.2

### Added
- Management service now provides `deleteTask(taskId)` for deleting tasks only in `pending`, `error`, or `finished` status.

## 1.4.1

### Fixed
- Management API task mapping now reads `missed_runs_strategy` from the database correctly, so `missedRunStrategy` is returned in task DTO/view payloads.

## 1.4.0

### Added
- Management methods to load a task by id and update pending task runtime settings.
- Separate management method to update periodic schedule fields for pending periodic tasks.
- Optional queue filter for task search parameters.

### Changed
- Renamed management search method from `findByStatus(...)` to `findByParameters(...)`.

## 1.3.0

### Added
- Cron-based periodic scheduling support with `repeat_type='cron'`.
- New `cron_expression` column in `tasks_queue` for storing cron schedules.

### Migration
Apply the following SQL to existing databases:

```sql
-- Add a dedicated column for cron schedules
ALTER TABLE tasks_queue
    ADD COLUMN IF NOT EXISTS cron_expression text DEFAULT NULL;

-- Recreate repeat_type check to allow cron
ALTER TABLE tasks_queue
    DROP CONSTRAINT IF EXISTS tasks_queue_repeat_type_check;

ALTER TABLE tasks_queue
    ADD CONSTRAINT tasks_queue_repeat_type_check
        CHECK (repeat_type IN ('fixed_rate', 'fixed_delay', 'cron'));

-- Ensure cron expression is never blank when provided
ALTER TABLE tasks_queue
    DROP CONSTRAINT IF EXISTS tasks_queue_cron_expression_not_blank;

ALTER TABLE tasks_queue
    ADD CONSTRAINT tasks_queue_cron_expression_not_blank
        CHECK (cron_expression IS NULL OR btrim(cron_expression) <> '');

-- Keep interval and cron fields mutually exclusive and consistent with repeat_type
ALTER TABLE tasks_queue
    DROP CONSTRAINT IF EXISTS tasks_queue_repeat_config_consistency;

ALTER TABLE tasks_queue
    ADD CONSTRAINT tasks_queue_repeat_config_consistency
        CHECK (
            (repeat_type IS NULL AND repeat_interval IS NULL AND cron_expression IS NULL)
                OR
            (repeat_type IN ('fixed_rate', 'fixed_delay') AND repeat_interval IS NOT NULL AND cron_expression IS NULL)
                OR
            (repeat_type = 'cron' AND cron_expression IS NOT NULL AND repeat_interval IS NULL)
        );
```
