fix(workspace): restore cache-short-circuit in enrich_peer_metadata_nonblocking
All checks were successful
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 8s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 10s
sop-tier-check / tier-check (pull_request) Successful in 10s
E2E API Smoke Test / detect-changes (pull_request) Successful in 23s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 23s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 23s
CI / Detect changes (pull_request) Successful in 25s
Runtime PR-Built Compatibility / detect-changes (pull_request) Successful in 27s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 6s
CI / Platform (Go) (pull_request) Successful in 5s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 6s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 5s
CI / Canvas (Next.js) (pull_request) Successful in 5s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 5s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Successful in 1m42s
audit-force-merge / audit (pull_request) Has been skipped
CI / Python Lint & Test (pull_request) Successful in 6m41s

PR #502 removed the cache check from enrich_peer_metadata_nonblocking
to "make test isolation deterministic", but this broke 5 tests that
depended on the cache-hit path:

- test_envelope_enrichment_uses_cache_when_present:
  KeyError: 'peer_name' (cache populated but not read)
- test_envelope_enrichment_fetches_on_cache_miss:
  KeyError: 'peer_name' (second push expected warm cache)
- test_envelope_enrichment_re_fetches_after_ttl:
  KeyError: 'peer_name' (stale TTL expected to re-fetch)
- test_enrich_peer_metadata_nonblocking_cache_hit_returns_immediately:
  assert None is not None (expected record on cache hit)
- test_enrich_peer_metadata_nonblocking_cache_miss_schedules_fetch:
  assert None is not None (expected record on second call)

Restore the cache check inside the _enrich_in_flight_lock critical
section. The lock is necessary because without it, a cache-hit thread
and a cache-miss thread could both pass the in-flight gate before
either populates the cache, spawning two parallel GETs for the same
peer. The cache check inside the lock serialises this correctly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Molecule AI · core-be 2026-05-11 17:05:30 +00:00
parent 0ed272e537
commit b129d213f0

View File

@ -187,12 +187,21 @@ def enrich_peer_metadata_nonblocking(
canon = _validate_peer_id(peer_id)
if canon is None:
return None
current = time.monotonic()
# Schedule background fetch unless one is already in flight for this
# peer. The synchronous version atomically reads-then-writes; the
# async version splits that into "schedule fetch" + "fetch fills
# cache later." The in-flight set keeps a flurry of pushes from
# one peer (e.g., a chatty agent) from spawning N parallel GETs.
# The cache check lives inside the lock so a concurrent cache-hit
# thread and a cache-miss thread don't both pass the in-flight gate
# before either has populated the cache.
with _enrich_in_flight_lock:
cached = _peer_metadata_get(canon)
if cached is not None:
fetched_at, record = cached
if current - fetched_at < _PEER_METADATA_TTL_SECONDS:
return record
if canon in _enrich_in_flight:
return None
_enrich_in_flight.add(canon)