Skip to content

Let forecasting jobs report how many beliefs they computed and saved #2823

Open

Description

@Flix6x

Follow-up to #2821 / #2822, agreed in this review thread. A forecasting job's result should say how many beliefs it computed and how many it recorded, like reporting and scheduling jobs do.

Today

  • A cycle job (run_train_predict_cycle_job → run_forecast_cycle) returns a bare float. It is the wall-clock seconds the cycle spent training plus predicting, measured with time.time() in TrainPredictPipeline.compute_cycle. It leaves out loading the regressors' data for saving, the CSV export and the save itself.
  • The wrap-up job (run_train_predict_wrap_up_job) returns None. It only logs the status of each cycle job.
  • Nobody reads the float as a job result: not the wrap-up job, not the API, not the UI. The only reader is the synchronous path (run_forecast without as_job), which sums it into the log line "Train-Predict Pipeline completed successfully in X seconds". Each cycle also logs its training and prediction times itself.
  • The counts already exist in run_forecast_cycle: len(bdf) is computed, and save_forecast returns the number saved. They never reach the job result.
  • When a forecast is triggered with more than one cycle, the job ID it hands back points at the wrap-up job, so GET /api/v3_0/jobs/<uuid> shows null.

Design

The same shape that #2822 settled on for the results of reporting, scheduling and plugin automation jobs (in ee6173c, with the recorded count renamed in 9f6e404): an outputs list with one entry per output sensor, holding the sensor (its ID), num-computed-beliefs and num-recorded-beliefs, and no totals. outputs_of_job_result in flexmeasures/data/services/generator_results.py builds it from what save_generator_results returns.

Cycle job:

{
  "outputs": [
    {"sensor": 12, "num-computed-beliefs": 96, "num-recorded-beliefs": 90}
  ]
}

Wrap-up job, summing its cycle jobs per sensor:

{
  "outputs": [
    {"sensor": 12, "num-computed-beliefs": 672, "num-recorded-beliefs": 650}
  ]
}
  • num-computed-beliefs counts every belief the cycle returned, including NaN values. num-recorded-beliefs leaves out NaN values and beliefs already on record (see save_forecast). On a dry run, nothing is recorded.
  • The wrap-up job depends on all cycle jobs, so it only runs once they have all finished, and can fetch their results to sum them.
  • The float is dropped from the result:
    • The job's own started-at/ended-at in GET /api/v3_0/jobs/<uuid> already say how long it took.
    • The split between training and prediction stays in the logs.
    • The synchronous path can keep summing the runtime internally (ForecastCycleResult.runtime) for its log line.
  • A changed job result type is an API change, so it gets an API changelog line, which should say the float is gone.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UBBvKZkzbfEPKctwTN8SDf

Activity

  1. added this to the 1.2.0 milestone on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions