-
Notifications
You must be signed in to change notification settings - Fork 3
[ERP-4395] Cache schema to improve perfomance and reduce memory use #780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next_release
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR aims to improve GraphQL performance by caching the dynamically generated Graphene schema and invalidating that cache when registry definitions change.
Changes:
- Memoize
create_dynamic_schema()usingcache_memoizeand addclear_dynamic_schema_cache(). - Invalidate the schema cache on registry form/section/CDE changes.
- Add new signal receivers intended to invalidate the schema cache on
Registry/ContextFormGroupchanges.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
rdrf/report/schema.py |
Adds memoization to the dynamic schema builder and exposes an explicit cache invalidation hook. |
rdrf/rdrf/models/definition/models.py |
Hooks schema cache invalidation into model lifecycle events via Django signals. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rdrf/report/schema.py
Outdated
| @cache_memoize(settings.CACHE_DEFAULT_TIMEOUT) | ||
| def create_dynamic_schema(): | ||
| if not Registry.objects.all().exists(): |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cache_memoize uses the Django cache backend (db/memcached/etc) and will pickle the return value. A graphene.Schema built from dynamically created types and local resolver functions (closures/partials) is not pickleable, so caching create_dynamic_schema() this way is likely to raise a PicklingError at runtime when the decorator attempts to cache the schema.
Suggested fix: use a per-process in-memory cache (e.g., functools.lru_cache(maxsize=1) or a module-level singleton) and update clear_dynamic_schema_cache() to call cache_clear()/reset the module variable. If you truly need cross-process caching, cache a serializable representation (e.g., SDL) rather than the Schema object itself.
| @receiver([post_save, post_delete], sender="definition.Registry") | ||
| @receiver([post_save, post_delete], sender="definition.ContextFormGroup") |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The signal senders for registry_definition_changed are specified as strings ("definition.Registry" and "definition.ContextFormGroup"), but the actual model labels in this project appear to be under the rdrf app (e.g., settings installs the rdrf app, and other code references these models as "rdrf.Registry" / "rdrf.ContextFormGroup"). As written, this receiver likely never fires, so the dynamic schema cache won’t be invalidated when registries or context form groups change.
Suggested fix: use the model classes directly (sender=Registry / sender=ContextFormGroup) or update the string labels to "rdrf.Registry" and "rdrf.ContextFormGroup". It would also be good to add a test that creates/updates a ContextFormGroup or Registry and asserts create_dynamic_schema() reflects the change after invalidation.
| @receiver([post_save, post_delete], sender="definition.Registry") | |
| @receiver([post_save, post_delete], sender="definition.ContextFormGroup") | |
| @receiver([post_save, post_delete], sender=Registry) | |
| @receiver([post_save, post_delete], sender=ContextFormGroup) |
No description provided.