Skip to content

Fix detached DataSource and expired sensors when enqueuing forecast jobs#2034

Draft
Copilot wants to merge 5 commits intomainfrom
copilot/debug-detached-data-source-issue
Draft

Fix detached DataSource and expired sensors when enqueuing forecast jobs#2034
Copilot wants to merge 5 commits intomainfrom
copilot/debug-detached-data-source-issue

Conversation

Copy link
Contributor

Copilot AI commented Mar 17, 2026

get_or_create_source() only flushes a new DataSource — it never commits. When the API request context tears down without an explicit commit, the data source row is rolled back. The RQ worker then fails to find it by ID. A secondary issue: db.session.commit() expires all session objects, causing sensor references pickled into RQ jobs (future_regressors, past_regressors, sensor, sensor_to_save) to raise DetachedInstanceError on the worker.

Fixes

  • train_predict.py

    • db.session.merge(self.data_source) + db.session.commit() before enqueuing jobs — ensures the data source row exists in the DB when the worker runs
    • db.session.refresh(sensor) calls after commit to re-hydrate expired sensor objects before RQ serialises the job
    • New _reattach_if_needed() static helper consolidates the repeated merge-if-detached-or-expired pattern used across sensor, sensor_to_save, future_regressors, and past_regressors in run_cycle()
    • Fixed run_wrap_up(): Job.fetch() requires an explicit connection argument (was raising TypeError)
    • Return value of run() changed from a bare job ID string to {"job_id": ..., "n_jobs": ...}
  • api/v3_0/sensors.py — consume pipeline_returns["job_id"]

  • cli/data_add.py — use local as_job variable (was reading parameters.get("as_job")); consume pipeline_returns["n_jobs"]

Tests

  • Regression test test_data_source_committed_before_forecast_jobs: demonstrates the flush-without-commit bug (source disappears after rollback) and verifies the merge+commit fix makes it findable in a fresh query
  • Added multi-cycle parametrize case (retrain-frequency: PT12H, 2 cycles, as_job=True) — previously untested code path for wrap-up jobs
  • Fixed forecast-count assertion to multiply by n_cycles; switched search_beliefs to most_recent_beliefs_only=False to count all saved beliefs across cycles
Original prompt

In #2011 we were facing a detached data source (representing the forecaster) that was not being committed by the server when the forecast trigger API was valued. Subsequently, the worker could not find the data source in the db and failed the forecasting job. A db session.merge(self.data_source) fixed that, but does not seem to address the root cause for the data source to become detached. Additionally, it lead to a test failing on a detached sensor (a future regressor), which is puzzling me.

You must:

  • have the test specialist debug the issue using debug statements, not just inspecting code.
  • have the test specialist add a test that reproduces the original data source issue if the db.session.merge(self.data_source) is not there. (You may need to locally revert the relevant commit to check.)
  • verify all tests pass before stopping the session.

Custom agent used: review-lead
Orchestrates team of specialist agents for comprehensive code reviews and synthesizes their findings into unified recommendations


💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

@read-the-docs-community
Copy link

read-the-docs-community bot commented Mar 17, 2026

Documentation build overview

📚 flexmeasures | 🛠️ Build #31853186 | 📁 Comparing cbff3b4 against latest (f1707fc)


🔍 Preview build

Show files changed (3 files in total): 📝 3 modified | ➕ 0 added | ➖ 0 deleted
File Status
genindex.html 📝 modified
_autosummary/flexmeasures.data.models.forecasting.pipelines.train_predict.html 📝 modified
api/v3_0.html 📝 modified

Copilot AI and others added 4 commits March 17, 2026 23:01
The TrainPredictPipeline creates a DataSource via get_or_create_source()
which only flushes (not commits) the new source. When the RQ worker runs
later, the data source may not be found in the DB if the API request's
transaction was never committed.

Fix:
- Add db.session.merge(self.data_source) + db.session.commit() in
  train_predict.py before queuing forecast jobs to ensure the data
  source is persisted in the DB before jobs run
- After commit, refresh sensor objects to prevent DetachedInstanceError
  when RQ pickles self.run_cycle for the worker
- Re-attach detached sensor objects in run_cycle() at job execution time
  to handle the case where sensors are expired/detached after unpickling

Also fix run_wrap_up to pass the Redis connection to Job.fetch(), and
update return values to include both job_id and n_jobs for callers.

Update sensors.py and data_add.py to use the new dict return value.
…d fix assertions

Changes:
1. Add new parametrize case for multi-cycle forecasting (retrain-frequency PT12H,
   forecast-frequency PT12H → 2 cycles, 2 viewpoints per cycle) with as_job=True

2. Fix search_beliefs call to use most_recent_beliefs_only=False so that all
   belief times from all cycles are returned

3. Fix forecast count assertion to account for n_cycles when computing expected
   count (multi-cycle jobs produce n_cycles times more forecasts)

4. Fix as_job section to use pipeline_returns['job_id'] (dict return value from
   updated run() method) and fix wrap-up job vs single-job detection logic

5. Add regression test test_data_source_committed_before_forecast_jobs:
   - Demonstrates that flushed-but-not-committed data sources are lost on rollback
   - Verifies that the merge+commit fix makes data sources findable after expunge
   - Provides clear debug output of SQLAlchemy instance states
- Fix 'viewpoint' -> 'viewpoints' in comment
- Add ', and' before n_cycles in assertion message for clarity
- Improve comment on db.session.merge() to explain why merge is needed
  before commit (get_or_create_source flushes but does not commit)
Co-authored-by: Flix6x <30658763+Flix6x@users.noreply.github.com>
Copilot AI changed the title [WIP] Debug detached data source issue in forecasting Fix detached DataSource and expired sensors when enqueuing forecast jobs Mar 17, 2026
Copilot AI requested a review from Flix6x March 17, 2026 23:10
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.

2 participants