Issue #1293: fix: give the GraphQL filter input cache the lifetime of one schema build - #1314
Merged
Merged
Conversation
… one schema build input_type_cache was module-level and keyed by type name alone, so the second schema built in a process silently reused the first one's input types. It is now created per build in generate_graphql_root_types, next to mutable_input_type_cache, and threaded through create_input_type. The two test workarounds that reset the module-level cache are removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
12 tasks
bjagg
approved these changes
Sep 26, 2026
bjagg
left a comment
Contributor
There was a problem hiding this comment.
Approving. 30 pass; reverting the brick's code to main fails 8 (the new test plus the ones the removed workarounds were masking). Hoisting the cache back to module level is caught. I checked there's no second module-level cache in the brick, core.py is the only caller, and the new parameter is required rather than a mutable default, which would have reintroduced this. The #1311 merge-order note is accurate: whichever lands second needs the one monkeypatch.setattr(... "input_type_cache" ...) line removed.
bjagg
added a commit
that referenced
this pull request
Sep 26, 2026
Resolve CHANGELOG.md with #1310 and #1313 by keeping every entry. In test_core.py, keep main's file plus this branch's TestMutationFailureDoesNotLeakBody, minus its monkeypatch.setattr(type_factory, "input_type_cache", {}) line: #1314 removed that module attribute, so the line raised AttributeError (the step #1314's PR body describes).
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 of Change
Problem.
components/lif/openapi_to_graphql/type_factory.pydeclaredinput_type_cacheat module level, keyed by type name alone, and nothing ever cleared it. So the second schema built in a process reused the first schema's filter input types. Two schemas whosePersonhad entirely different queryable fields silently shared onePersonInput.mutable_input_type_cache, its sibling, was already per build.As #1293 says, this isn't reachable in production today:
bases/lif/api_graphql/core.pybuilds the schema once, inlifespan. It did already bite tests, though. Two test helpers carried amonkeypatch.setattr(type_factory, "input_type_cache", {})workaround, and without it a test passed alone but failed in the suite. It would also turn any future schema hot-reload after an MDR change into a silent bug.Solution. This is the issue's suggested change.
generate_graphql_root_types(core.py) now createsinput_type_cache = {}next tomutable_input_type_cacheand passes it tocreate_input_type. That gains aninput_type_cacheparameter, matchingcreate_mutable_input_type. The module-level variable is gone.create_input_typeisn't exported from the package (__init__.pyexportsgenerate_graphql_root_types/generate_graphql_schema), andcore.pyis its only caller.Both test workarounds are removed: the one the issue names in
test_core.py::TestQueryPlannerFailureReachesCaller, and a second copy intest_lif_client_header.pythat #1301 added. Their_schemahelpers no longer takemonkeypatch.Side effects. None in production. The service builds one schema per process, and it's built the same way.
How reviewers should test it.
Related Issues
Closes #1293
Refs #1131
Type of Change
Project Area(s) Affected
Checklist
uv run ruff check)uv run ruff format)uv run ty check)Testing
TestInputTypesArePerSchemaBuildbuilds two schemas in one process: one wherePersonhas a single queryable fieldalpha, and one where it'sbeta. It reads each schema'sPersonInputfields by introspection.mainit fails exactly as the issue describes:assert {'alpha'} == {'beta'}. The second schema reused the first's input type.The removed workarounds are the third acceptance criterion. With them gone, all 30 tests in
test/components/lif/openapi_to_graphql/pass in the same run, including the ones that used to need them.pre-commit run --fileson all four changed files is green, including the full pytest suite.No README or CHANGELOG change: the component README doesn't mention the cache, and nothing changes for a caller.
Additional Notes
Merge order with #1311 (#1309), measured by a trial merge. #1311's new
TestMutationFailureDoesNotLeakBodycarries a third copy of the same workaround line.test_core.py: both PRs append a test class at the end of the file. Keep both classes.AttributeError: <module 'lif.openapi_to_graphql.type_factory'> has no attribute 'input_type_cache', becausemonkeypatch.setattrrefuses a missing attribute. Delete that one line (monkeypatch.setattr(type_factory, "input_type_cache", {})) and the brick passes (31 passed in the trial).Whichever PR merges second needs both steps.
mainrequires branches to be up to date, so that PR's CI will surface step 2 if it's missed.Shared brick (#1171).
components/lif/openapi_to_graphqlis packaged bylif_graphql_apionly, and its deploy workflow already covers the brick.🤖 Generated with Claude Code