Files
sientia-dataops-laborious_t…/e2e/scenarios.md
vitor-aignosi e6018af23f SIENTIAPDE-1646
Update README, requirements, and E2E tests for improved configuration and functionality

- Enhanced the README with updated model configuration examples, including the addition of an alias for production.
- Removed the `requirements-light.txt` file and updated `requirements-local.txt` and `requirements.txt` to replace `asyncua` with `opcua`.
- Refactored E2E test scenarios to utilize scenario input files for better maintainability and clarity.
- Improved test coverage for MinIO offload functionality and added new helper functions for loading scenario inputs.
- Updated `values.yaml` to reflect new global configurations and environment variables for the laborious worker.
2026-05-07 17:02:25 -03:00

402 lines
13 KiB
Markdown

# E2E Scenario Documentation - Predictions Batch
This document describes the end-to-end scenarios for `predictions_batch` and its child workflows:
`prediction_process` and `format_and_export_prediction`.
It is a functional reference of scenario behavior, inputs, and expected outcomes.
## Execution Context
- Tests run under `e2e/` and are marked with `@pytest.mark.integration`.
- PostgreSQL and MinIO are provisioned with testcontainers.
- `test_minio_offload.py` uses real MinIO I/O; other scenario suites may use stubs/mocks for optional outputs.
---
## 1. Main Workflow Scenarios
Source: `e2e/test_predictions_batch_main_workflow.py`
### 1.1.1 Happy Path - Complete Success
**Summary**: Full workflow succeeds with valid query and default gate behavior.
**Description**:
- Query returns rows for a model.
- `prediction_process` runs transform and predict paths.
- Final prediction and transformed data are persisted.
**Expected Outcome**:
- Exactly one prediction row is created.
- Transform rows are created.
- Confidence/status/comments are success values.
### 1.2.1 SQL Query Execution Error
**Summary**: Invalid SQL leads to no persisted prediction.
**Description**:
- Input query is invalid.
- Load step fails and workflow follows error/short-circuit path.
**Expected Outcome**:
- No prediction rows for the model.
- Workflow does not require retry-loop assumptions in assertions.
### 1.2.2 Missing Required Parameters
**Summary**: Missing required fields prevent workflow completion path.
**Description**:
- Required input key (e.g. `query`) is omitted.
- Workflow fails to produce actionable input for child flow.
**Expected Outcome**:
- No prediction rows are persisted.
- Workflow handle may require explicit terminate in E2E harness.
### 1.2.3 Invalid Datetime Column Specification (de-prioritized)
**Summary**: Legacy invalid datetime-column case is retained only as low-priority legacy coverage.
**Description**:
- `datetime_columns` references non-existing columns.
- Behavior may vary by query shape and parser fallback.
**Expected Outcome**:
- No predictions persisted in the covered legacy assertion path.
- Scenario is not considered primary behavior coverage.
---
## 2. Prediction Process Scenarios
Source: `e2e/test_predictions_batch_prediction_process.py`
### 2.1 Input Gate Path Decisions
#### 2.1.1 CONTINUE
**Summary**: Input filter flags quality issue but allows continuation via default path.
**Description**:
- Input gate returns `CONTINUE`.
- MLFlow transform/predict are skipped.
- Export path persists default-style prediction with warning context.
#### 2.1.2 STOP
**Summary**: Input filter blocks processing.
**Description**:
- Input gate returns `STOP`.
- Workflow exits without export.
#### 2.1.3 REPEAT with history
**Summary**: Prior prediction is reused.
**Description**:
- Input gate returns `REPEAT`.
- `repeat_last_prediction` path is executed using existing historical row.
#### 2.1.4 REPEAT without history
**Summary**: Repeat requested but no previous prediction exists.
**Description**:
- Input gate returns `REPEAT`.
- No prior row is available to duplicate.
**Expected Outcome**:
- No new prediction rows are created for the model.
### 2.2 Transform Gate Decisions
#### 2.2.1 CONTINUE on transform response error
**Summary**: Transform response is degraded, but workflow continues.
#### 2.2.2 STOP on transform response error
**Summary**: Transform response error blocks downstream processing.
#### 2.2.3 REPEAT on transform response error
**Summary**: Transform response error triggers repeat-last-prediction path.
#### 2.2.4 STOP on transform content NaN
**Summary**: Content gate (`NAN_VALUES`) blocks on all-NaN transform payload.
### 2.3 Predict Gate Decisions
#### 2.3.1 CONTINUE on predict response error
**Summary**: Predict response degraded; workflow exports with degraded metadata.
#### 2.3.2 STOP on predict response error
**Summary**: Predict response error blocks export.
#### 2.3.3 REPEAT on predict response error
**Summary**: Predict response error routes to repeat-last-prediction.
### 2.4.1 Priority Conflict Resolution
**Summary**: Deterministic selection when multiple filters produce different flags.
**Description**:
- Multiple filters may produce `STOP`, `CONTINUE`, and/or `REPEAT`.
- `path_priority` defines precedence.
**Expected Outcome**:
- Highest-priority flag is applied consistently.
- Executed branch matches configured priority ordering.
---
## 3. Format and Export Scenarios
Source: `e2e/test_predictions_batch_format_export.py`
### 3.1 Output Combination Scenarios
#### 3.1.1 Default prediction export
**Summary**: Non-`None` path flag uses `format_default_prediction`.
**Description**:
- Default prediction is generated.
- Transform export is skipped.
- Optional outputs (PI/OPC) still execute when configured.
#### 3.1.2 OPC only
**Summary**: Postgres + OPC writes, PI Web API disabled.
#### 3.1.3 PI Web API only
**Summary**: Postgres + PI writes, OPC disabled.
#### 3.1.4 Postgres only
**Summary**: Both optional outputs disabled; only Postgres persistence and metrics.
#### 3.1.5 No transformed data export
**Summary**: Prediction is persisted; transformed table is not written.
### 3.2 Degraded-but-successful Completion
#### 3.2.1 PI Web API write error
**Summary**: PI write failure does not fail workflow.
**Expected Outcome**:
- Workflow completes.
- Prediction persisted with degraded confidence/comments (PI error semantics).
#### 3.2.2 OPC write error
**Summary**: OPC write failure does not fail workflow.
**Expected Outcome**:
- Workflow completes.
- Prediction persisted with OPC degraded confidence/comments.
#### 3.2.3 PI Web API partial write error
**Summary**: Partial PI acknowledgement is treated as degraded success.
**Expected Outcome**:
- Workflow completes.
- Prediction persisted with PI error confidence and descriptive comment.
### 3.3.1 Combined Optional Outputs (PI + OPC)
**Summary**: Both external output channels are enabled together.
**Description**:
- PI Web API and OPC configs are both present.
- Output mutation order matters for final persisted payload.
**Expected Outcome**:
- PI write executes before OPC write in workflow sequence.
- Final Postgres payload reflects any confidence/comment updates.
- OPC metrics are emitted when tag writes return response times.
---
## 4. MinIO Offload Scenarios
Source: `e2e/test_minio_offload.py`
### 4.1.1 Forced offload to MinIO
**Summary**: Very low threshold forces parquet upload.
**Description**:
- Payload is offloaded (`object_key` present, inline data absent/empty).
- Object is present in MinIO under `prediction_datasets/...`.
- Retrieval reconstructs the dataframe.
### 4.1.2 Full workflow with offloaded load payload
**Summary**: Offload path works during full `predictions_batch` execution.
**Expected Outcome**:
- Workflow completes.
- Prediction row is persisted.
### 4.2.1 Inline payload below threshold
**Summary**: Data remains inline when threshold is not exceeded.
**Expected Outcome**:
- Payload stores inline `data`.
- `object_key` is `None`.
- Downstream persistence behavior matches offload scenario semantics.
---
## 5. Drift Workflow Scenarios
Source: `e2e/test_drift.py`
The drift suite mocks `sientia.ModelAnalysis.ModelAnalysis` (not installed; see
`CODE_ISSUES.md` issue #1) through the controllable `_FakeModelAnalysis` stub
exposed by the `model_analysis_stub` fixture. The `mlflow_repository_stub`
provides the reference-data CSV via `download_artifacts`. Every scenario asserts
postgres rows in `predictions_schema.drift` against this canonical schema:
`id, model_id, feature, method, value, drift, chunk, timestamp, timestamp_end, accurate, created_at, updated_at`.
### 5.1 Happy paths
#### D.1.1 Full pipeline persists all columns with reference data
**Summary**: ModelAnalysis returns a deterministic drift dataframe; the
reference CSV is downloaded from the MLflow stub.
**Expected Outcome**:
- One row per `(chunk, feature, method)` plus a `multivariate` block per chunk.
- Every drift column is populated and `accurate=True`.
- `timestamp_end` preserves the high-precision string (`HH:MM:59.999999999`).
- `p_value` is dropped before persistence.
- `drift` flags propagate per `(feature, method)` configuration.
#### D.1.2 30% fallback when reference data is unavailable
**Summary**: `get_reference_data` fails alias resolution and returns `None`;
`calculate_drift` uses the first 30% of target rows as reference.
**Expected Outcome**:
- Persisted rows carry `accurate=False`.
- A `MODEL_METRICS_REFERENCE_DATA_WARNING` notification is emitted to MongoDB.
### 5.2 Filtering / dedup invariants
#### D.2.1 Deduplication and `p_value` removal
**Summary**: ModelAnalysis returns duplicate `(timestamp, method, feature)` rows
plus a `p_value` column.
**Expected Outcome**:
- Duplicates are collapsed keeping the first occurrence.
- `p_value` is absent from the persisted rows.
#### D.2.2 Out-of-range timestamps filtered
**Summary**: Drift rows whose timestamps are not present in the target window
must be discarded before persistence.
### 5.3 Failure paths
#### D.3.1 Empty target data short-circuits the workflow
**Summary**: `load_custom_query` returns no rows; ModelAnalysis is never
instantiated and no drift rows are written.
#### D.3.2 ModelAnalysis raises during dataframe assembly
**Summary**: `get_drift_metrics_dataframe` raises. The activity catches the
error, sends a `MODEL_METRICS_GET_DRIFT_METRICS_ERROR` notification, and the
workflow completes without persisting drift rows.
### 5.4 Configuration paths
#### D.4.1 Default drift metrics propagated to analyzer
**Summary**: Omitting `drift_metrics` defaults to
`['kolmogorov_smirnov', 'jensen_shannon', 'wasserstein']` and forwards the
exact list to `detect_univariate_drift`.
#### D.4.2 Invalid `chunk_period` raises ValueError
**Summary**: Anything other than `min` / `s` is rejected by `calculate_drift`.
#### D.4.3 `chunk_period='s'` keeps seconds in timestamp filtering
**Summary**: Truncated `YYYY-MM-DD HH:MM` rows are filtered out when chunking
runs at second granularity.
---
## 6. Simple Metrics Workflow Scenarios
Source: `e2e/test_simple_metrics.py`
Validates `predictions_schema.simple_metrics_data` columns:
`id, model_id, metric, value, timestamp, data_size, interval_minutes, created_at`.
### 6.1 Happy paths
#### S.1.1 rmse/mse/mae/r2 happy path
**Summary**: Prediction/target pairs are inserted; the activity computes all
four metrics with closed-form expected values.
**Expected Outcome**:
- One row per metric is persisted; all columns populated.
- `data_size` matches the joined row count and `interval_minutes=60`.
#### S.1.2 Subset metrics
**Summary**: Requesting `metrics=['rmse']` writes only the rmse row.
### 6.2 Edge cases
#### S.2.1 Zero-variance target returns r2=0
**Summary**: When all targets are equal, `ss_tot=0`; the activity must guard
against division by zero and return `r2=0`.
### 6.3 Failure paths
#### S.3.1 No overlapping data short-circuits persistence
**Summary**: With no `laborious_data` rows for the configured target variable
the workflow exits before `calculate_simple_metrics` and writes nothing.
---
## 7. Minimal Retrain Workflow Scenarios
Source: `e2e/test_minimal_retrain.py`
The MLflow registry is fully mocked (no real artifacts in test container).
Validates `predictions_schema.retrain_reports` columns:
`id, model_id, model_name, timestamp, status, version, mlflow_run_id, mlflow_experiment_id, created_at`.
### 7.1 Happy path
#### MR.1.1 Successful retrain + promotion
**Summary**: Training data loads via MinIO offload, `wrapper.retrain` succeeds,
the new version is promoted to the `production` alias.
**Expected Outcome**:
- Report row has success status, `version='7'`, `mlflow_run_id='retrain-run-id'`,
`mlflow_experiment_id='experiment-id'`.
- `mlflow.log_artifact` is called with the input CSV.
- `promote_to_alias` is called once with the resolved version and alias.
### 7.2 Failure paths
#### MR.2.1 Wrapper retrain raises
**Summary**: `wrapper.retrain` raises `RuntimeError`. The activity returns
`success=False`, `update_production_model` is NOT invoked.
**Expected Outcome**:
- Report row carries the error message and `version`/`mlflow_*` columns are NULL.
#### MR.2.2 Missing `model_config.target`
**Summary**: Empty model config short-circuits before any MLflow call.
**Expected Outcome**:
- Report row carries the explicit guard message.
- `get_cached_model` is never invoked.
#### MR.3.1 No training data
**Summary**: The training query returns no rows; the workflow does not
persist any report row. The current code raises plain `ValueError` from the
workflow function, which Temporal treats as a workflow-task failure (see
`CODE_ISSUES.md` issue MR-1).
---
## Input Contract Reference
Common scenario input fields:
- `schedule_name`
- `model_name`
- `model_id`
- `query`
- `schema`
- `table_name`
- `transform_table_name`
- `input_filters`
- `mlflow_transform_filters`
- `mlflow_predict_filters`
- `path_priority` (default order: `STOP`, `CONTINUE`, `REPEAT`)
- `save_transform`
- `prediction_store_policy`
- `model_config.target`
- `datetime_columns` (when query returns temporal fields)
Optional outputs:
- `opc_output_config`
- `pi_web_api_output_config`