Repository navigation
Raise the economy cache schema version so ×100 decile results stop being served - #4026
Conversation
Since its move to .py 4.x, the simulation API has returned decile.relative and the UK wealth_decile.relative as percentages (x100) instead of fractions (PolicyEngine/policyengine-sim-api#827). The Public API keeps economy results in Redis for 30 days, and their cache key does not change when only the simulation API's code changes, so results already cached would keep serving the x100 values after the simulation API fix (PolicyEngine/policyengine-sim-api#904) is deployed. Raising RUNTIME_CACHE_SCHEMA_VERSIONS["economy_impact"] from 3 to 4 changes the cache version in every economy and budget-window cache key, so results stored under 3 are no longer found and are recomputed. Tests pin the new version and show that an impact stored under the version-3 cache version is not matched by a lookup with the current one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4026 +/- ##
===========================================
+ Coverage 51.11% 87.72% +36.60%
===========================================
Files 242 258 +16
Lines 14441 15864 +1423
Branches 2307 2594 +287
===========================================
+ Hits 7382 13917 +6535
+ Misses 6436 1280 -5156
- Partials 623 667 +44 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Thanks Anthony, this looks right. I approve.
I confirmed the precondition: the prod deploy of #904 (sim-api run 39879445060, commit 1fe19571) redeployed policyengine-simulation-py6-7-5, so new economy results from the Public API now carry fractions. It's safe to merge this now.
The change and the tests look good: version 4 makes the exact and the prefix lookups miss the version-3 entries, and the new tests fail at 3. The one-time recompute of budget-window results is fine, since they hold no decile output.
Agreed that the ×100 values in saved v1 report records need a follow-up. Is there an issue for it yet?
Brings in #4026 (raise the economy cache schema version from 3 to 4) and the 5.7.0 "Update PolicyEngine API" release commit. Conflicts: - tests/unit/services/test_reform_impacts_service.py: both sides added a new test at the end of the file. This branch added test_a_briefly_kept_error_expires_and_leaves_other_records; master added test_impact_cached_under_previous_economy_schema_version_is_not_matched. Kept both, this branch's test first. The imports master added for its test (constants, get_economy_impact_cache_version) merged without conflict. Merged without conflict, checked by hand: - policyengine_api/constants.py: RUNTIME_CACHE_SCHEMA_VERSIONS ["economy_impact"] is 4 (master), and UK_COUNTRY_REGIONS, UK_REGION_REGISTRY_CODES and LOCAL_AREA_BREAKDOWN_REGIONS are kept (this branch). - pyproject.toml: package version 5.7.0 (master) and the policyengine[models]==6.10.0 pin (this branch). - uv.lock: policyengine-api 5.7.0 (master) with this branch's .py 6.10.0 dependency set (policyengine 6.10.0, policyengine-core 3.33.3, policyengine-uk 2.132.6). `uv lock --check` passes. - tests/unit/test_constants.py: both sides' additions kept. - CHANGELOG.md and changelog.d/: master's 5.7.0 entry and its removal of the released remove-economy-comparison fragment, plus master's economy-cache-decile-fractions fragment; this branch's fragments are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #4025
What and why
Since its move to .py 4.x, the simulation API has returned
decile.relativeand the UKwealth_decile.relativeas percentages (multiplied by 100) instead of fractions. Production economy results have carried these values since 2026-06-29, when the Public API started requesting .py 4.18.3. PolicyEngine/policyengine-sim-api#827 tracks the bug, and PolicyEngine/policyengine-sim-api#904 fixes it by dividing by 100 inbuild_decile_output.The Public API caches economy results in Redis for 30 days (
REFORM_IMPACT_TTL_SECONDS, with jitter). A lookup matches on the scope (country, policy pair, region, dataset and period), the cache version (ReformImpactIdentity.api_version, fromget_economy_impact_cache_version) and the options hash. The cache version is a digest of the country package, .py and policyengine-core versions plusRUNTIME_CACHE_SCHEMA_VERSIONS["economy_impact"]. The options hash covers the request options, the dataset, the model and .py versions, and the simulation app name. None of these change when only the simulation API's code changes, so after #904 is deployed, results already cached for .py 6.7.5 would keep being served with multiplied-by-100 values for up to 30 days.This PR raises
RUNTIME_CACHE_SCHEMA_VERSIONS["economy_impact"]from 3 to 4. The cache version changes frome3…toe4…, so lookups read a different Redis scope index and don't find results stored under version 3. The next request for each economy result recomputes it.Budget-window cache
BudgetWindowCache.build_keytakes itsapi_versionfrom the sameget_economy_impact_cache_versioncall (through_build_economic_impact_setup_options), so this change also gives every budget-window result a new key, and budget-window results are recomputed once. Budget-window results hold only yearly budget totals (tax revenue, benefit spending and budgetary impact), not decile output, soBUDGET_WINDOW_CACHE_SCHEMA_VERSIONdoesn't need its own change.When to merge
Only after PolicyEngine/policyengine-sim-api#904 is merged and deployed to the simulation app the Public API uses, which is
policyengine-simulation-py6-7-5today. Merging earlier would recompute results that are still multiplied by 100 and cache them under the new version for another 30 days.Interaction with the .py 6.10.0 update (#4024)
#4024 updates .py to 6.10.0, which changes both the cache version digest and the options hash, so results cached for 6.7.5 stop being reused once it ships, with or without this PR. That only helps if the simulation app for .py 6.10.0 also includes #904's fix. Without it, that app computes and caches new multiplied-by-100 results under the new key.
What this doesn't fix
Report outputs already saved to v1 report records keep the multiplied-by-100 values, because they are stored in the database and are not read back from the economy cache. Correcting them is a follow-up.
RUNTIME_CACHE_SCHEMA_VERSIONS["report_output"]is unchanged here.Tests
tests/unit/test_constants.py::TestEconomyImpactCacheVersionpinsRUNTIME_CACHE_SCHEMA_VERSIONS["economy_impact"]at 4, and checks that the US and UK cache versions start withe4and still fit the 10-characterapi_versioncolumn.tests/unit/services/test_reform_impacts_service.py::test_impact_cached_under_previous_economy_schema_version_is_not_matchedstores a completed impact under the version-3 cache version in the in-memory cache, then checks that the exact and options-hash-prefix lookups with the current cache version return nothing, while a lookup with the old version still finds it.With the version still at 3, all four new tests failed (
assert 3 == 4,'e30e9091da'.startswith('e4'), and the version-3 impact returned by the current-version lookup). They pass at 4.Local checks:
make format,ruff check .andruff format --check .: cleanuv run --frozen --extra dev mypy: no issuesmake test: 3285 passedpython scripts/run_quality_guards.py: passedEnvironment variables
None change. This PR changes one Python constant, its tests and a changelog fragment.
🤖 Generated with Claude Code