Skip to content

Run reports via CLI and API - #2298

Open
Flix6x wants to merge 146 commits into
mainfrom
feat/2288-report-trigger-api
Open

Run reports via CLI and API#2298
Flix6x wants to merge 146 commits into
mainfrom
feat/2288-report-trigger-api

Conversation

@Flix6x

@Flix6x Flix6x commented Jul 11, 2026

Copy link
Copy Markdown
Member

Description

Closes #2426.

This PR makes one-off reports available as background jobs, independently from report automations. It brings the non-automation-specific reporting infrastructure forward from #2297, #2290 and #2294 so the CLI and API functionality can be reviewed, released and tested on its own.

  • Register a dedicated reporting RQ queue with configurable job timeouts and worker support.
  • Add flexmeasures add report --as-job for queueing reports from the CLI.
  • Add POST /api/v3_0/assets/<id>/reports/trigger for queueing reports through the API.
  • Persist the reporter configuration before queueing so a worker can reconstruct the reporter.
  • Store report results as beliefs and expose the job through the existing job-status and asset-status functionality.
  • Resolve reporter input and output sensors through the data generator itself, including configuration-based dependencies such as Profit-or-loss price sensors.
  • Require read access to every input and configuration sensor and create-children access to every output sensor.
  • Require every output sensor to belong to the asset in the URL or one of its descendants.
  • Validate and authorize the request before persisting the reporter data source or queueing work.
  • Apply the shared schedule/forecast/report trigger rate limit.
  • Add CLI, API, worker, authorization and end-to-end regression tests.
  • Document the reporting worker queue, API endpoint and permission model.
  • Added changelog item in documentation/changelog.rst.

The API request envelope is validated first. The selected reporter then validates config and parameters with its concrete schemas. FlexMeasures resolves and authorizes all declared dependencies before creating the reporting job.

Look & Feel

CLI

Queue a report instead of computing it in the CLI process:

flexmeasures add report \
  --reporter PandasReporter \
  --config report-config.json \
  --parameters report-parameters.json \
  --start 2023-04-10T00:00:00+00:00 \
  --end 2023-04-10T10:00:00+00:00 \
  --as-job

Process queued reports with a reporting worker:

flexmeasures jobs run-worker --queue reporting

--as-job stores report results in the database and therefore cannot be combined with --dry-run or --output-file.

API

The endpoint is included in the generated OpenAPI specification and can be tried interactively through Swagger UI:

  1. Start FlexMeasures and sign in with a user who can access the target asset.
  2. Open http://127.0.0.1:5000/api/v3_0/docs.
  3. Under Assets, expand POST /api/v3_0/assets/{id}/reports/trigger.
  4. Select Try it out.
  5. Enter the target asset ID, for example 42.
  6. Paste the following request body, replacing the sensor IDs with sensors available to your user.
{
  "reporter": "PandasReporter",
  "config": {
    "required_input": [{"name": "one"}, {"name": "two"}],
    "required_output": [{"name": "sum"}],
    "transformations": [
      {
        "df_input": "one",
        "method": "add",
        "args": ["@two"],
        "df_output": "sum"
      }
    ]
  },
  "parameters": {
    "input": [
      {"name": "one", "sensor": 12},
      {"name": "two", "sensor": 13}
    ],
    "output": [{"name": "sum", "sensor": 14}],
    "start": "2023-04-10T00:00:00+00:00",
    "end": "2023-04-10T10:00:00+00:00"
  }
}

Select Execute. Swagger UI shows the generated request and the server response. A valid request returns HTTP 202 Accepted using the canonical asynchronous-job response:

{
  "status": "ACCEPTED",
  "message": "Request has been accepted for processing.",
  "job": "<job UUID>",
  "job-url": "/api/v3_0/jobs/<job UUID>"
}

The response is defined by the generated OpenAPI documentation. The caller can follow job-url or use GET /api/v3_0/jobs/{uuid} in Swagger UI until the job finishes. The queued job records {"origin": "API"} in its metadata.

How to test

Automated tests

python -m pytest -q \
  flexmeasures/api/v3_0/tests/test_report_trigger_api.py \
  flexmeasures/api/v3_0/tests/test_rate_limiting.py \
  flexmeasures/cli/tests/test_data_add.py \
  flexmeasures/data/schemas/tests/test_reporting.py \
  flexmeasures/data/models/reporting/tests \
  flexmeasures/data/tests/test_generic_assets.py \
  flexmeasures/data/tests/test_reporting_service.py \
  flexmeasures/utils/tests/test_job_utils.py

The focused suite covers:

  • CLI queueing and reporter reconstruction from the stored data source.
  • The canonical HTTP 202 response and job-status URL.
  • API-to-worker execution and persisted output beliefs.
  • Anonymous, cross-organisation and sensor-level permission failures.
  • Source-filtered inputs and configuration-based price-sensor dependencies.
  • Output subtree enforcement.
  • Missing or invalid reporter inputs and outputs without database or queue side effects.
  • Shared trigger rate-limit registration.
  • Reporting queue configuration and timeout handling.

Latest local result: 119 passed, 22 warnings.

Manual test

  1. Choose two input sensors containing historical data and an output sensor below the asset used in the API URL.
  2. Create a valid Pandas reporter configuration and parameters file using fixed historical start and end times.
  3. Run flexmeasures add report ... --as-job and confirm a job is added to the reporting queue.
  4. Start flexmeasures jobs run-worker --queue reporting and confirm the job finishes and beliefs are stored on the output sensor.
  5. Submit the equivalent API request and confirm it returns HTTP 202 with job and job-url.
  6. Poll GET /api/v3_0/jobs/<job UUID> and confirm the job moves from queued to finished.
  7. Repeat with an unreadable input/configuration sensor and confirm HTTP 403 with no reporter data source or job created.
  8. Repeat with an output outside the URL asset subtree and confirm HTTP 422 with no reporter data source or job created.
  9. Repeat without required inputs or outputs and confirm HTTP 422 with no persistence or queue side effects.

Further Improvements

Recurring report automations, automation UI work and prepared report templates remain outside this standalone PR and continue in their respective follow-up work.

Related Items


Sign-off

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on code under GPL or another incompatible license.

Flix6x and others added 22 commits July 11, 2026 15:06
Automations are recurring tasks (for now: computing forecasts) defined per
asset. The recurrence is defined by a cron string, and the work to be done
is defined by a data generator (linked through a data source) together with
the parameters to call it with.

Includes a migration for the new table, and new dependencies on croniter
(cron matching/validation) and cron-descriptor (natural-language recurrence
descriptions).

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
- `flexmeasures add automation` creates an automation (active by default),
  validating the forecast parameters with the forecast parameter schema and
  storing the forecaster config on a data source.
- `flexmeasures edit automation` edits the name, recurrence (cron string)
  or activation status.
- `flexmeasures delete automation` deletes an automation.
- All three record their events in the asset's audit log.
- `flexmeasures jobs run-automations` queues jobs for all automations due
  this minute (to be run once per minute, e.g. via cron), with a Redis-based
  guard against duplicate runs within the same minute.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Data generators can now be told how their queued jobs got triggered (via the
CLI, the API or an automation), and the train-predict pipeline stores this
on the jobs as meta data. The asset's status page shows it in a new
'Created Via' column of the jobs table.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
GET /api/v3_0/assets/<id>/automations lists the automations defined on an
asset (without generator and parameters details). GET
/api/v3_0/assets/<id>/automations/<automation_id> additionally provides the
parameters, data generator info and counts of recently created jobs per job
status. Both are documented in the OpenAPI specs.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
/assets/<id>/automations shows the asset's automations in a tabbed view
(schedules and reports tabs are prepared but deactivated), with per-row
details (parameters, data generator, job counts) loaded asynchronously into
a modal. The page is linked in the breadcrumbs dropdown and links to the
status page, where recent jobs are listed.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
CI runners have no locale set (POSIX), which made cron-descriptor render
'At 06:00' while dev environments with an en_US-style locale rendered
'At 06:00 AM'. Request 24-hour format explicitly so the description is
deterministic across environments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pxkeq64jtENY7fiWjwUsVS
- Escape automation names (and other user-controlled strings) in the
  Automations page and the status page's jobs table, closing two stored
  HTML/script injection sinks.
- Wipe parameter state on the (possibly shared) cached data generator before
  each automation run, so automations sharing a generator data source don't
  pollute each other's runs.
- Count automation job stats under the forecast target sensor(s) from the
  automation's parameters, which may belong to a different asset.
- Release the per-minute Redis guard when a run fails, so a retry within the
  same minute can still queue jobs.
- Return 404 (as documented) for nonexistent automation ids on the detail
  endpoint, and check permissions on the asset, so automation ids can no
  longer be enumerated across accounts via 403-vs-422 differences.
- Use ondelete=SET NULL for the generator FK: deleting a data source no
  longer silently deletes automations.
- Delegate Automation ACL to the asset's ACL instead of duplicating it.
- Extract the config/parameters assembly shared by `add forecasts` and
  `add automation` into a helper (which no longer drops falsy config values).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Completes the previous commit, whose staged files were dropped by an
interrupted pre-commit run: template escaping, shared-generator state reset,
job stats under target sensors, Redis guard release on failure, 404 for
nonexistent automations, SET NULL generator FK, ACL delegation, and the
shared CLI config/parameters assembly helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
The scheduling job creators accept an optional trigger dict (stored as job
meta data), like the forecasting pipeline already does. The API trigger
endpoint records origin API; the CLI and automations follow in the next
commit. The status page's 'Created Via' column picks this up automatically.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Automations now also support the 'schedules' type:

- `flexmeasures add automation --type schedules` validates the parameters as
  a schedule trigger message (per the AssetTriggerSchema, as accepted by the
  API trigger endpoint, without the asset id). The schedule 'start' may be
  omitted, in which case each run schedules from the run time (floored to the
  message's resolution, if given) — a fixed start draws a warning.
- The runner dispatches schedules automations to the same job creators as the
  API trigger endpoint (sequential or simultaneous), recording trigger meta
  data (origin automation) on the queued jobs; `flexmeasures add schedule
  --as-job` now records origin CLI.
- Job stats for schedules automations are counted from the scheduling job
  cache (asset-level wrap-up jobs and per-sensor device jobs).
- The UI automations page's Schedules tab is now enabled, with automations
  filtered by type per tab.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
- New endpoints on assets: POST /automations (create, validating parameters
  by automation type), PATCH /automations/<id> (name, cron string, activation
  status) and DELETE /automations/<id>. Managing automations requires the
  same principals that may delete the asset (account admins and consultants).
- The UI automations page gets a 'New automation' modal and per-row
  (de)activate and delete actions, shown to users with management rights.
- Creation, update and deletion logic (incl. audit log records) moved into
  the automations service, shared by the CLI commands and the API endpoints.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
- Activate the reporting queue (it was prepared but commented out), including
  worker help texts and queue cleanup.
- Reporters accept as_job: a job is queued (with trigger meta data) that
  rebuilds the reporter from its data source, computes the report and saves
  the results to the database.
- `flexmeasures add report --as-job` queues such a job; reporting jobs show
  up in the asset's jobs overview (status page and API).

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Automations can now compute reports on a recurring basis:

- `flexmeasures add automation --type reports --reporter <class>` stores the
  reporter config on a data source (steady across runs, so all report results
  attribute to the same source) and validates the report parameters.
- The report window resolves freshly on each run: 'start-offset'/'end-offset'
  fields (comma-separated Pandas offsets, applied to the run time in the
  first output sensor's timezone) express a rolling window, and without any
  timing fields the window defaults to the last cron period (from the
  previous cron fire time until the run time). Absolute start/end still work,
  but draw a warning.
- The API creation field 'forecaster' is generalized to 'generator' (also
  accepting reporter classes), and the UI's New automation modal gains data
  generator and config fields; the Reports tab is now enabled.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Each automation run is recorded in Redis; a report automation without timing
fields then reports on the period since its actual last run, falling back to
the last cron period when no last run is known (e.g. on the first run, or
after a Redis flush). This gives gapless coverage even when runs are missed.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Consolidates the shared automations concept (model, lifecycle, runner
deployment, provenance) into documentation/features/automations.rst, with
the per-feature pages linking to it and keeping only their type-specific
parameter semantics.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Add POST /api/v3_0/assets/<id>/reports/trigger, which queues a one-off
reporting job on the reporting queue, mirroring how forecasts and
schedules are triggered via the API. The job status can be polled via
the generic GET /api/v3_0/jobs/<uuid> endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Flix6x and others added 7 commits July 11, 2026 22:20
- API automation creation now checks that the caller may read every sensor
  referenced in the parameters/config and record data on the sensors the
  automation writes to, closing a cross-account data read/write hole.
- `add report --as-job` implies --save-config (the worker rebuilds the
  reporter from its data source, so jobs without stored config always crashed).
- Report automation parameters are validated with the chosen reporter's own
  parameters schema, not the base schema.
- Invalid start-offset/end-offset strings are rejected at creation instead of
  being silently skipped at run time (which yielded empty report windows).
- run_report_job wipes the shared cached reporter's parameter state, like the
  automation runner already did, so consecutive jobs in one worker process
  don't pollute each other.
- Default report windows now anchor to the end of the last *successfully*
  covered window, recorded by the reporting job upon success — failed jobs no
  longer create permanent reporting gaps, and the enqueue-time minute-rollover
  gap is gone (the recorded anchor is the window end itself).
- The cron-period fallback window is computed in the platform timezone,
  matching how the runner decides when automations fire.
- Job stats for schedules automations also scan flex-model device sensors
  (which may belong to child assets), so failed per-device jobs show up.
- The trigger provenance kwarg is excluded from the job cache hash, so
  identical schedule requests from different origins dedupe again.

Part of #2288

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
The report trigger endpoint now applies the same sensor-access guard as
automation creation: the caller must be able to read every input sensor and
record data on every output sensor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
…essage format

PR #2303 makes click report the validation message rather than the offending
value, which changes the exact wording of this error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rbix8k1JfeUWNXEmHEZVpX
Merge current main, resolve the shared forecasting and documentation changes, regenerate the lockfile, and move the automation migration after the current migration head.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Reject cron expressions with seconds, year fields, or aliases because the automation runner executes once per minute.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Test valid five-field expressions and reject unsupported seconds, year, and alias formats.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Describe per-automation timezone selection and the successful-coverage model used by recurring reports. The documentation now distinguishes the claimed cron occurrence from delayed runner time and explains how first runs, daylight-saving transitions, and out-of-order worker completions determine report windows.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Commit the fixture-owned sensor setup after rejected report automation requests so the shared API test database does not retain an idle transaction during teardown. This keeps the complete automation API module deterministic while preserving assertions that no unauthorized automation was created.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- The report trigger branch was based on the pre-review report automation stack and no longer compiled after the centralized reporter sensor checks landed.

Change:
- Merge the updated report automation branch, preserve both changelog histories, and adapt the trigger endpoint to the shared sensor resolution and current asynchronous API conventions.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- Report triggers can name inputs in both request parameters and reporter configuration, while output sensors must stay within the asset selected by the endpoint.

Change:
- Isolate report-trigger mutations with a fresh database and cover private parameter inputs, private ProfitOrLossReporter price sensors, sibling outputs, rejected transaction cleanup, queue side effects, and the canonical accepted-job response.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- The report trigger endpoint now follows the same dependency and output-scope guarantees as report automations and returns the shared asynchronous job representation.

Change:
- Document input and output sensor authorization, the asset-subtree boundary, and the canonical accepted-job response for one-off report triggers.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>

@nhoening nhoening left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice, and my opinion is that it can be pulled ahead and already tested by itself - one-off reporting jobs are valuable on their own, for instance to make things like our HEMS script more useful. They also do not rely on db migrations, thus are an easy addition we might include in v1.0.0 (or v1.1.0) so we can test them in practice before automations are rolled out in a later version.

Automations might also be a complex feature which we'll be hesitant to roll out quickly - by prioritizing this PR, we de-couple this.

But: we'd need a few smaller things that are introduced in (currently) lower-stacked PRs.

So my proposal (next to some smaller suggestions, see below) is to extract a few things from these PRs into this PR, which are not automation-specific, but enable to run reporters as jobs. The scope of this PR then becomes: "one-off reports as background jobs, their API endpoint, and the authorization machinery needed to expose that safely".

All these changes are 1-2 lines or extracting helper functions (maybe removing a few automation logic bits in them):

  • Register the reporting Redis queue (#2297)
  • extract create_reporting_job() and run_report_job() (#2297)
  • Reporter._compute(..., as_job=True) (#2297)
  • DataGenerator.input_sensors, output_sensors and _resolve_sensors() (#2290)
  • asset_is_in_subtree() (#2290)
  • check_sensor_access() (#2294)
  • resolve_data_generator_sensors() (#2294)
  • Reporter.input_sensors and output_sensors (#2297)
  • ProfitOrLossReporter.input_sensors for price dependencies in config (#2297)
  • Require non-empty report inputs and outputs (#2297)
  • Worker/deployment documentation for the reporting queue in documentation/host/queues.rst (#2297)

The genuinely important integration points are:

  • Persisting the reporter configuration before queueing so the worker can reconstruct it.
  • Clearing cached parameters inside the worker.
  • Checking config-based input sensors, not only parameter inputs.
  • Starting a production worker for the reporting queue.
  • Running an end-to-end test that confirms the worker stores report beliefs.

Next to this scope extension using exiting code, here are a few other small things I found wanting:

Rate-limit documentation is now inaccurate.

The endpoint uses @limit_triggers(), so reports consume the same shared trigger quota as schedules and forecasts. However, the plan CLI help and configuration docs still say “schedule or forecast.” Those should also mention reports. I would also add AssetAPI.trigger_report to the rate-limit registration test.

The PR description is stale.

It still describes 200 PROCESSED, a report response field, and output ownership as “not hard-enforced.” The implementation correctly returns 202 ACCEPTED with canonical job/job-url fields and does enforce the output subtree.

Optional test improvement.

The endpoint test stops after asserting that a job was queued. The base stack tests the reporting worker separately, so this is not a blocker, but one API-path test that runs the worker and verifies output beliefs would be much better to test what this PR really is doing, in effect.
Maybe we could Adapt test_run_report_automation from #2297; rewrite it without an automation

Comment thread flexmeasures/data/schemas/reporting/__init__.py Outdated
Context:
- One-off reports were computed only in the CLI process, so the API could not safely hand expensive report work to a worker.

Change:
- Add reporter dependency metadata, a dedicated RQ queue and worker service, CLI queueing support, job provenance, status-page tracking and configurable reporting timeouts.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- The report trigger endpoint must stand on main without the automation service while preventing callers from reading or writing sensors outside their permissions and requested asset subtree.

Change:
- Add the report request envelope, reusable data-generator authorization helpers, subtree validation and a rate-limited endpoint that validates and authorizes before persisting a reporter source or queueing work.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- Report jobs cross API authorization, RQ serialization and worker persistence boundaries where code inspection alone cannot establish correctness.

Change:
- Cover CLI queueing, canonical API responses, trigger registration, queue timeouts, invalid requests, cross-organisation and config-sensor access, output subtree enforcement, side-effect-free rejection and API-to-worker belief storage.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- Hosts and API users need to know how to queue, process and authorize reports after moving computation out of the request or CLI process.

Change:
- Document the reporting worker queue, CLI and API entry points, sensor permission model, shared trigger rate limit and generated OpenAPI contract.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- The standalone report-job story adds both a public API endpoint and a CLI option in PR #2298.

Change:
- Record the new background-report capability and its canonical asynchronous response in the main, API and CLI changelogs.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
@BelhsanHmida BelhsanHmida self-assigned this Aug 17, 2026
@BelhsanHmida BelhsanHmida linked an issue Aug 17, 2026 that may be closed by this pull request
Context:
- Specialized reporter schemas accidentally made inherited input or output requirements optional, allowing malformed API and CLI requests to reach the reporting queue and persist unusable data sources.

Change:
- Preserve required dataflow fields in specialized schemas and validate the canonical reporter input/output contract before accessing or committing a reporting data source.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- Missing specialized reporter inputs or outputs previously produced an API 500, queued doomed jobs, or left reporter data sources behind.

Change:
- Reproduce malformed Aggregator and Profit-or-loss requests through schemas, the API and CLI, and assert that service-level validation runs before persistence or queueing.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- The report trigger work was rebuilt on main, while the protected remote branch retained its former stacked history and could not be rewritten.

Change:
- Join the histories without restoring the superseded stacked files, allowing the standalone implementation to be pushed through a normal fast-forward update.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
@BelhsanHmida
BelhsanHmida marked this pull request as ready for review August 17, 2026 23:02
@BelhsanHmida
BelhsanHmida changed the base branch from feat/2288-report-automations to main August 17, 2026 23:03
Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
@BelhsanHmida BelhsanHmida changed the title API endpoint to trigger reports as jobs Run reports via CLI and API Aug 17, 2026
Context:
- Reporting queues expose the same configurable timeout mechanism as other job queues, but report jobs overrode it with a fixed one-hour value.

Change:
- Leave the job timeout unset during creation so RQ applies the reporting queue's configured default when it enqueues the job.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- Asset status data labelled every failed job as a scheduling failure, including newly visible reporting jobs.

Change:
- Build the failure label from the job's queue so scheduling, forecasting and reporting failures are identified accurately.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- The bundled Docker worker did not listen to the reporting queue, so accepted CLI and API report jobs could remain queued indefinitely in the standard setup.

Change:
- Add the reporting queue to the worker process started by Docker Compose.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- The report trigger advertised a canonical asynchronous response, but its generated OpenAPI operation documented only the 202 status code.

Change:
- Describe the required status, message, job and job-url fields and provide a concrete accepted-response example in the generated API contract.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- Host documentation omitted reporting from configurable timeout and installation guidance, and its combined worker example left shell pipe characters unquoted.

Change:
- Document reporting timeout configuration, include reporting in worker setup commands and quote the multi-queue value so the example executes as intended.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
Context:
- Queue registration tests did not prove that created report jobs inherited the configured timeout, and status tests did not exercise reporting failures.

Change:
- Assert the effective timeout on a CLI-created report job and verify that failed reporting jobs retain their queue-specific status label.

Signed-off-by: Mohamed Belhsan Hmida <mohamedbelhsanhmida@gmail.com>
@BelhsanHmida

Copy link
Copy Markdown
Contributor

@nhoening Thanks, I followed your proposal and made #2298 standalone on main.

It now includes the reporting queue and worker, flexmeasures add report --as-job, the shared
data-generator sensor-resolution and authorization helpers, reporter input/output
dependencies, output-subtree enforcement, rate-limit documentation/tests, and the
API-to-worker end-to-end test that verifies stored beliefs.

I also added defensive validation for non-empty reporter inputs and outputs before
the reporter data source is persisted.

The ReportTriggerSchema docstring has been updated to clarify that it validates
only the request envelope, while the selected reporter validates its concrete
configuration and parameters.

I have also updated the PR description to reflect the 202 job/job-url response
and the enforced permission model. Ready for another review once CI finishes.

@BelhsanHmida
BelhsanHmida requested a review from nhoening August 18, 2026 01:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run one-off reports as background jobs via CLI and API

3 participants