feat(backend): add calculatedAt metric freshness indicator (Closes #1240) - #1350
Merged
K1NGD4VID merged 1 commit intoAug 30, 2026
Merged
Conversation
Banx17
force-pushed
the
fix/1240-metrics-stale-indicator
branch
from
August 30, 2026 07:17
9ef0078 to
697e036
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a visible stale/cached indicator to the admin metrics dashboard by including a
calculatedAtISO-8601 timestamp in theGET /v1/admin/metricsresponse. The timestamp reflects when the underlying aggregation actually ran (when the metrics payload was stored in the in-process cache), not when the HTTP response is serialized. This lets operators/dashboards tell whether the numbers reflect the last few seconds or up to the full cache TTL (60s) ago.Type of Change
Related Issues
Closes #1240
Changes Made
The metrics cache (
MemoryCache,backend/src/lib/redis.ts) already records the timestamp at which each cache entry was populated (createdAt, exposed viacache.getMetadata()). No new caching pattern was invented — this reuses the same convention already used byclaimable.service.ts(cachedAt).Changed files:
backend/src/routes/v1/admin.routes.tswithCalculatedAt()helper that readscache.getMetadata(ADMIN_METRICS_CACHE_KEY).createdAtand attaches acalculatedAtfield (falling back to the current time only if metadata is unavailable).HITpath (behindwithLiveIndexerCounters) and the cache-MISSpath.backend/tests/integration/admin-metrics.test.tscalculatedAtis present in valid ISO 8601 format.calculatedAtreflects the aggregation time and is stable across multiple responses served from the same cache entry (does not drift to "now" on every call).Acceptance Criterion
"The
/v1/admin/metricsresponse includes a timestamp field reflecting when the underlying aggregation ran."Met as follows:
MISS,buildAdminMetrics()runs and the result is stored viacache.set(ADMIN_METRICS_CACHE_KEY, payload, 60). The cache entry'screatedAtis that store time, i.e. when the aggregation actually ran.calculatedAtis derived from it.HIT, the cached payload is served andcalculatedAtis still derived from the same cache entry'screatedAt, so two consecutive requests within the 60s TTL return the samecalculatedAt— proven by the new stability test. It is never recomputed as "now" at response-serialization time on a cache hit.Testing
Test Coverage
Commands & Real Results
Backend has no lint script (
backend/package.jsonhas nolint);.github/workflows/ci.ymlrunsnpm run build+npx vitest run --coverage --reporter=basicfor the backend. Frontend lint also runs in CI but no frontend files are touched here.npm run build(backend — includestsctype-check):Targeted test file:
Full backend suite (CI-equivalent:
npx vitest run --coverage --reporter=basic; real-Postgres integration tests self-skip locally because Docker/DATABASE_URLare unavailable — they run in CI):Coverage thresholds (60%) all pass. The only uncleanness in the local run is a pre-existing unhandled rejection in
tests/workers.index.test.ts(stream-runway-workerlogger mock,default.error is not a function) that also reproduces on the clean base branch with these changes stashed; it does not fail any test.Checklist