Skip to content

fix(spp_cel_domain): probe the legacy metric service by capability, not model name (#443) - #535

Open
gonzalesedwin1123 wants to merge 3 commits into
19.0from
fix-443-cel-domain-legacy-indicator-probe
Open

gonzalesedwin1123 wants to merge 3 commits into
19.0from
fix-443-cel-domain-legacy-indicator-probe

Conversation

@gonzalesedwin1123

Copy link
Copy Markdown
Member

Part of #443 (weekly ci-full red). First of the per-module PRs; this one is a real production bug, not a test problem.

Problem

spp_cel_domain/models/cel_executor.py _exec_metric (and the aggregate-metric path) checks "spp.indicator" in self.env as a stand-in for "the legacy spp_indicators evaluation service is installed" and then calls svc.evaluate(...) / svc.enqueue_refresh_from_domain(...). That service lived in the archived openspp-modules repo. In OpenSPP2, spp_statistic was renamed to spp_indicator (f4384f0) and its spp.indicator is a publishable-indicator configuration model with no evaluate(). No OpenSPP2 commit ever defined either method.

So on any database with spp_indicator installed (the SP-MIS starter via spp_mis_demo_v2, spp_api_v2_gis, spp_indicator_studio), every metric() over a cached or external variable whose cache is not fresh raises AttributeError: 'spp.indicator' object has no attribute 'evaluate' inside the executor. cel_service.compile_expression swallows it and returns valid=False, so the whole expression compiles to an error instead of the documented graceful empty result.

Per-module CI never sees it: spp_cel_domain does not depend on spp_indicator, so the "no service" branch runs there. In the weekly SP-MIS ci-full job it shows as TestCELExecutorCacheLookup.test_metric_lookup_respects_period_key / test_metric_lookup_empty_cache_graceful failing with False is not true on result["valid"].

Fix

A _legacy_metric_service() helper resolves the service by capability (callable(getattr(service, "evaluate", None))) instead of by model name; both call sites use it and take the existing graceful branch when it returns None. The misleading "consider installing spp_indicators" warning text is corrected. No behaviour change on databases without spp_indicator.

spp_cel_domain 19.0.2.1.0 → 19.0.2.1.1 + HISTORY fragment. README/index.html left for CI's pinned generator.

Evidence

Reproduced locally with -i spp_cel_domain,spp_indicator --test-tags /spp_cel_domain:TestCELExecutorCacheLookup:

  • before: 2 failed, 0 error(s) of 7 tests (the two tests above)
  • after: 0 failed, 0 error(s) of 7 tests

Module suite: 0 failed, 0 error(s) of 651 tests. New tests/test_legacy_metric_service.py (3 tests) covers the probe in per-module CI: no model → no service; a model without evaluate() → no service; a model with evaluate() → returned. All pre-commit hooks pass on the changed files. An SP-MIS ci-full run is dispatched on this branch; its failing-test set should lose exactly these two tests against the 2026-09-20 baseline.

Not in this PR (tracked in #443 research / follow-ups)

Deleting the other dead legacy probes in the same file (spp.indicator.value, spp.indicator.registry, spp.indicator.invalidation.buffer), and finishing the ADR-017 TODO so a not-fresh lookup refreshes through spp.data.cache.manager instead of returning empty.

…ot model name

_exec_metric and the aggregate-metric path took the presence of
spp.indicator in the registry to mean the retired spp_indicators
evaluation service was installed and called evaluate() on it. OpenSPP2's
spp_indicator reuses that model name for an unrelated configuration
model, so wherever it is installed every metric() over a variable whose
cache was not fresh raised AttributeError inside the executor and the
expression compiled to an error instead of the graceful empty result.

Both sites now resolve the service through _legacy_metric_service(),
which requires a callable evaluate(), and fall back to the SQL fast path
otherwise.

Refs #443
@codecov

codecov Bot commented Sep 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.79%. Comparing base (1a3c591) to head (270b70f).

Files with missing lines Patch % Lines
spp_cel_domain/models/cel_executor.py 77.77% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             19.0     #535      +/-   ##
==========================================
- Coverage   76.91%   75.79%   -1.13%     
==========================================
  Files         704      736      +32     
  Lines       45774    51541    +5767     
==========================================
+ Hits        35205    39063    +3858     
- Misses      10569    12478    +1909     
Flag Coverage Δ
spp_analytics 93.25% <ø> (ø)
spp_api_v2_change_request 73.37% <ø> (ø)
spp_api_v2_cycles 71.03% <ø> (ø)
spp_api_v2_data 77.77% <ø> (ø)
spp_api_v2_entitlements 70.23% <ø> (ø)
spp_api_v2_gis 74.60% <ø> (ø)
spp_api_v2_programs 92.22% <ø> (ø)
spp_api_v2_simulation 71.19% <ø> (ø)
spp_approval 50.85% <ø> (ø)
spp_base_common 91.07% <ø> (ø)
spp_case_cel 89.50% <ø> (ø)
spp_case_entitlements 100.00% <ø> (ø)
spp_case_programs 100.00% <ø> (ø)
spp_cel_domain 63.87% <77.77%> (?)
spp_cel_event 85.34% <ø> (?)
spp_cel_load_testing 98.11% <ø> (ø)
spp_programs 67.58% <ø> (ø)
spp_registry 89.00% <ø> (ø)
spp_security 69.56% <ø> (ø)

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

Files with missing lines Coverage Δ
spp_cel_domain/models/cel_executor.py 63.64% <77.77%> (ø)

... and 31 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…he no-service path

Review round: the probe checks evaluate() and
enqueue_refresh_from_domain() on the model class (a field carrying one
of those names is a non-callable descriptor and never touches access
checks); both no-service branches append a no_service entry to
metrics_info so previews can show that metric values were unavailable;
the tests use a real recordset as the name-only stand-in, assert the
probed model name, and cover the evaluate-only case; changelog states
the actual behaviour (empty match set, not an SQL fast path) and the
deployer-visible degradation.

Refs #443
@gonzalesedwin1123

Copy link
Copy Markdown
Member Author

Full-stack evidence: SP-MIS ci-full dispatched on this branch (run 35563004376, at 0e1175a) vs the 2026-09-20 weekly baseline (run 35499069639).

@gonzalesedwin1123
gonzalesedwin1123 marked this pull request as ready for review September 21, 2026 05:46
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