Skip to content

Add scoped full recalculation to Impulse reporting - #95

Open
tombonfert wants to merge 6 commits into
mainfrom
feature/trigger_scoped_full_recalc
Open

Add scoped full recalculation to Impulse reporting#95
tombonfert wants to merge 6 commits into
mainfrom
feature/trigger_scoped_full_recalc

Conversation

@tombonfert

Copy link
Copy Markdown
Collaborator

Summary

What

Adds an optional full_recalculation config that names aggregations, events, and/or calculated channels to fully recompute on the next incremental run, regardless of whether their definition hash changed. Listed entities recompute over all containers and fully replace their gold rows, while everything else stays incremental.

Why

Previously there was no way to force a full recompute of a specific entity whose definition was unchanged (for example, to backfill after a persistence fix or corrected upstream data). The only options were a full-mode run (recomputes everything, expensive) or artificially changing the definition.

How

The feature hooks into the existing changed/unchanged grouping. split_by_hash_change gained a force_recalc_names argument that promotes hash-unchanged items into the "changed" bucket, reusing the entire existing changed-path machinery (all-container solve plus delete-by-source pruning). No persistence-layer changes were needed. It is a no-op in full mode, where everything already recomputes.

Changes

  • config/config_parser.py: new FullRecalculation model and optional full_recalculation field on ImpulseConfig.
  • core/report_utils.py: force_recalc_names param on split_by_hash_change, plus full_recalc_names, registered_names_by_kind, and validate_full_recalculation_scope helpers.
  • core/report.py: wires the config scope into the three grouping call sites and validates the scope at the start of determine_report (raises on names that match no registered entity).

Tests

  • Unit: promotion/no-op behavior in split_by_hash_change, config parsing, and fail-fast validation on unknown names.
  • Integration: an incremental run where a hash-unchanged aggregation is scoped for recalc is recomputed across all containers (verified on real values), while a non-listed unchanged aggregation sharing the same fact table is left untouched.

Test Plan

  • Unit tests added/updated
  • Manual testing completed
  • Documentation updated (if applicable)

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • No new linter warnings introduced

- Introduce `FullRecalculation` config section naming aggregations, events,
  and calculated channels to recompute over all containers on the next
  incremental run, regardless of definition-hash changes.
- Wire the override into `split_by_hash_change` so listed entities are promoted
  to the changed bucket and fully replace their gold rows.
- Validate configured names against registered entities in
  `Report.determine_report` to fail fast on typos or stale names.
- Add integration and unit tests covering config parsing, validation, and
  end-to-end scoped recalculation behavior.
Move `full_recalc_names`, `registered_names_by_kind`, and
`validate_full_recalculation_scope` from private `Report` methods to
`report_utils.py` so they can be reused and unit-tested independently.
Update `Report` to delegate to the shared utilities while preserving the
existing fail-fast validation and per-kind force-recalc behavior.
Remove the explicit `kinds` parameter from
`validate_full_recalculation_scope` and iterate over the keys of
`registered_names` instead. Update the single caller in `Report` to
match, simplifying the API and ensuring validated kinds stay in sync
with the entities actually registered for a report.
@tombonfert
tombonfert requested a review from a team as a code owner September 9, 2026 11:51
@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.60%. Comparing base (c06c3ef) to head (a44ac55).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #95      +/-   ##
==========================================
+ Coverage   89.50%   89.60%   +0.09%     
==========================================
  Files          62       62              
  Lines        5591     5625      +34     
  Branches      686      694       +8     
==========================================
+ Hits         5004     5040      +36     
+ Misses        466      464       -2     
  Partials      121      121              
Flag Coverage Δ
query_engine 86.10% <ø> (ø)
reporting 94.42% <100.00%> (+0.16%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/impulse_reporting/config/config_parser.py 97.26% <100.00%> (+0.07%) ⬆️
src/impulse_reporting/core/report.py 92.78% <100.00%> (+0.70%) ⬆️
src/impulse_reporting/core/report_utils.py 97.64% <100.00%> (+0.22%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Use the config field names (`events`, `aggregations`, `calculated_channels`) as the kind keys passed to `full_recalc_names` and `validate_full_recalculation_scope`, replacing the old singular aliases and the internal `by_kind` mapping.
- Pass registered entity lists directly into validation and derive names there with `get_name()`, removing the `registered_names_by_kind` helper.
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.

1 participant