Use do_orm_execute for DML driven invalidation - #3045
Draft
whabanks wants to merge 1 commit into
Draft
Conversation
Many dao methods for updating / deleting leverage legacy sqlalchemy DML statements `Query.update()` and `Query.delete()`. These DML queries bypass the typical session ORM events like `after_commit` and `after_flush`. This prevents us from relying solely on ORM events for cache invalidation. Modernized DML syntax (`session.execute(<someQuery>)`) can be intercepted via `do_orm_execute` allowing us to follow the same event driven invalidation patterns for both session ORM changes and changes resulting from DML statements - Add `do_orm_execute` event listener - Add `cache_invalidating_dml` wrapper to execute DML statements and attach cache metadata to the `session.info` - Add `_queue_cache_invalidation` to store deduplicated cache invalidation actions to be executed post-commit - Migrate / modernize DML statements from legacy `Query.update()/delete()` to `session.execute(<query))`
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.
Summary | Résumé
Experimentally branched off of: #3033
Many dao methods for updating / deleting leverage legacy sqlalchemy DML statements
Query.update()andQuery.delete(). These DML queries bypass the typical session ORM events likeafter_commitandafter_flush. This prevents us from relying solely on ORM events for cache invalidation. Modernized DML syntax (session.execute(<someQuery>)) can be intercepted viado_orm_executeallowing us to follow the same event driven invalidation patterns for both session ORM changes and changes resulting from DML statementsdo_orm_executeevent listenercache_invalidating_dmlwrapper to execute DML statements and attach cache metadata to thesession.info_queue_cache_invalidationto store deduplicated cache invalidation actions to be executed post-commitQuery.update()/delete()tosession.execute(<query))How does this work?
Bulk DML queries in SQLAlchemy bypass session.dirty and after_flush instance detection. Statements like the one below are both legacy syntax from v1.4 and do not trigger typical session ORM events. (
after_flush,after_commit, etc.)The helper method
cache_invalidating_dml()adds cache metadata to the SQL statement that can be later extracted. Note the updated query syntax, this facilitates listening todo_orm_executeevents and is central to enabling event driven invalidation for DML queries.Behind the scenes cache metadata is included:
{ "cache_invalidation_entity_ids": { "user_id": user.id, } }_intercept_bulk_operations()is attached to thedo_orm_executeevent. Whendb.session.execute(statement)is run, it executes and:updateordeletePermission_queue_model_invalidations()after_commitorafter_rollbackevents to fire, so that we only invalidate after successful mutation, or drop the invalidations when rolling backPermissionentity in theCACHE_INVALIDATION_REGISTRYafter_commitevent fires, signalling successful data changes and_invalidate_cache_after_commitis called to invalidate the keyAt a high level
Benefits of this approach
ORM session based actions
CACHE_INVALIDATION_REGISTRYentries for the associated entity exist and clear the keys that it should.DML based statements
updateordeletestatements that affect cached values with the helper methodCACHE_INVALIDATION_REGISTRYentries for the associated entity exist and clear the keys that it should.CACHE_INVALIDATION_REGISTRYis technically global, it's read-only at runtime and will never be mutated.invalidate_group_keyscall maintains it's own local scan cursor, therefore parallel scans should not corrupt one another.Drawbacks
This would add some latency to API responses when executing an update or delete. The silver lining here is that all subsequent gets on that entity would hit cache cache instead of the DB and thus should offset added latency. You trade one slightly longer API call for many subsequent faster API calls.
Test instructions | Instructions pour tester la modification
TODO: Fill in test instructions for the reviewer.
Release Instructions | Instructions pour le déploiement
None.
Reviewer checklist | Liste de vérification du réviseur