Skip to content

fix(runtime): include entrypoint in the handler cache key - #32

Merged
rlemke merged 1 commit into
mainfrom
fix/dispatcher-entrypoint-cache-key
Aug 2, 2026
Merged

fix(runtime): include entrypoint in the handler cache key#32
rlemke merged 1 commit into
mainfrom
fix/dispatcher-entrypoint-cache-key

Conversation

@rlemke

@rlemke rlemke commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Problem

RegistryDispatcher._load_handler cached the resolved handler callable keyed by (module_uri, checksum) — dropping the entrypoint. Two facets registered from the same module (same module_uri + checksum) but with different entrypoints both received the first-cached callable, silently mis-routing every facet after the first to a single handler.

Domain packages register one dispatch entrypoint per module (routing on the facet name internally), which masked this. A handler module that exposes N distinct entrypoints — one per facet — hits it directly: e.g. a BuildMap facet dispatched to a sibling FetchGasPrices handler and returned the wrong return schema ({layer: …} instead of {html_path: …}), which then broke a downstream map.html_path reference.

Found while standing up a multi-facet handler module on the runtime.

Fix

Key the cache by (module_uri, checksum, entrypoint). One-line change in _load_handler; the _module_cache type annotation updated to the 3-tuple with an explanatory comment.

Tests

  • New regression test_distinct_entrypoints_same_module_do_not_collide — two entrypoints in one module must each dispatch to their own handler, checked in both dispatch orders. Verified it fails on the old key and passes on the new.
  • Updated the existing test_checksum_change_evicts_cache assertion for the new 3-tuple key.
  • Full suites green: test_dispatcher.py, test_registry_runner.py, test_runner_service.py, test_inline_dispatch.py253 passed.

Risk

Low. The cache becomes strictly more specific; domains using a single entrypoint per module are unaffected (their key just gains a constant third element). No behavior change except correct routing for multi-entrypoint modules.

🤖 Generated with Claude Code

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@rlemke

rlemke commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Note on the lint check: the failure is pre-existing on main, not introduced by this PR.

The 3 files changed here pass both linters cleanly:

  • ruff check facetwork/runtime/dispatcher.py tests/runtime/test_dispatcher.py tests/runtime/test_registry_runner.pyAll checks passed!
  • ruff format --check on those files → 3 files already formatted

Running CI's repo-wide commands locally shows the failures are in unrelated files (36 would-reformat + 25 ruff check errors, e.g. unused pytest imports in test_parser.py / test_validator.py) that this PR does not touch. Kept the PR focused on the dispatcher fix rather than bundling a repo-wide reformat.

@rlemke
rlemke force-pushed the fix/dispatcher-entrypoint-cache-key branch from 9c4470e to e117bca Compare August 2, 2026 03:12
@rlemke

rlemke commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Update — the red lint / test / typecheck checks are pre-existing on main, not introduced here.

Evidence: main's own latest CI run is failure (gh run list --branch mainCI: failure). This PR's changes are clean against all three:

  • lint — the 3 changed files pass ruff check and ruff format --check; the repo-wide failures are in ~36 unrelated files.
  • typecheckmypy facetwork/runtime/dispatcher.py0 errors (I fixed the one annotation this PR touched, the module_cache property return type). Remaining mypy errors are in unrelated files (validator.py, block_execution.py, evaluator.py).
  • test — the CI test job fails on a collection error in examples/osm-equity (ModuleNotFoundError: No module named 'tests…'), which interrupts the whole run before it gets to the change. Locally, the entire tests/runtime/ suite passes: 1257 passed, 24 skipped, including the new regression test.

So this PR is verified clean; the red checks are pre-existing CI-health debt (tracked separately). Happy to open a follow-up PR to green the CI (repo-wide ruff format, the mypy fixes, and the osm-equity collection error) if wanted — kept out of here to keep the dispatcher fix reviewable.

RegistryDispatcher._load_handler cached the RESOLVED handler callable keyed by
(module_uri, checksum) — dropping the entrypoint. Two facets registered from the
same module (same module_uri + checksum) but with different entrypoints both got
the first-cached callable, silently mis-routing every facet after the first to one
handler.

Domain packages register a single dispatch entrypoint per module, which masked
this; a handler module exposing N distinct entrypoints (one per facet) hit it —
e.g. a BuildMap facet dispatched to a sibling FetchGasPrices handler and returned
the wrong schema.

Fix: key the cache by (module_uri, checksum, entrypoint). Regression test added
(two entrypoints in one module must each dispatch to their own handler; fails on
the old key, passes on the new). Updated the checksum-eviction test for the new
3-tuple key. Full dispatcher + runner suites: 253 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rlemke
rlemke force-pushed the fix/dispatcher-entrypoint-cache-key branch from e117bca to fa66aaf Compare August 2, 2026 13:41
@rlemke

rlemke commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto main (picks up the pinned ruff + reformat from #33). lint ✅, test-go ✅, dispatcher suites pass (84 tests). The only red is typecheck — the pre-existing mcp version-drift tracked in #34, not from this change. Landing the verified dispatcher fix.

@rlemke
rlemke merged commit e8f08a3 into main Aug 2, 2026
18 of 22 checks passed
@rlemke rlemke mentioned this pull request Aug 2, 2026
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