Skip to content

Fix multi-database caching isolation and remove global state - #22

Closed
robinvandernoord wants to merge 2 commits into
masterfrom
fix/per-db-cache-models
Closed

robinvandernoord wants to merge 2 commits into
masterfrom
fix/per-db-cache-models

Conversation

@robinvandernoord

Copy link
Copy Markdown
Member

Summary

This PR fixes a critical issue where multiple TypeDAL databases with caching enabled in the same process would share cache tables, causing data corruption and incorrect cache hits/misses. The fix introduces per-database cache model instances while maintaining consistent table names across databases.

Key Changes

  • Introduced define_cache_models() and cache_models() functions: These functions manage per-database cache table bindings. define_cache_models() creates fresh subclasses of _TypedalCache and _TypedalCacheDependency for each database to avoid binding conflicts, while cache_models() retrieves the cache models bound to a specific database.

  • Updated all cache operations to accept db parameter: Functions like remove_cache(), remove_cache_for_table(), clear_cache(), clear_expired(), _insert_cache_entry(), and _fetch_cached_payload() now take a TypeDAL instance as their first parameter to ensure they operate on the correct database's cache tables.

  • Removed global state dependency: Eliminated the throw() helper and the pattern of relying on _TypedalCache._db to determine which database to use. This was fragile and failed when multiple databases existed.

  • Fixed TypeDAL.close() unbinding logic: Modified to only unbind models that are actually bound to the closing database instance, preventing interference with other database instances that may share model classes.

  • Updated cache invalidation hooks: Modified the after-insert, after-update, and before-delete hooks in define.py to capture the database instance and pass it to cache invalidation functions.

  • Added comprehensive multi-database test: New test file test_caching_multi_db.py validates that two databases with caching enabled maintain separate caches and that closing one database doesn't break caching on another.

Notable Implementation Details

  • Cache table names remain typedal_cache and typedal_cache_dependency across all databases for consistency
  • Each database gets its own subclass instances of the cache models, preventing binding conflicts
  • The module-level _TypedalCache and _TypedalCacheDependency classes remain unbound and serve as base classes only
  • Cache operations now properly raise RuntimeError if called on a database with caching disabled
  • CLI commands updated to pass the database instance to cache maintenance functions

https://claude.ai/code/session_0181W827mjAmRu6ECjtQTU5v

claude added 2 commits October 2, 2026 08:31
`_TypedalCache` and `_TypedalCacheDependency` were defined directly on each
caching-enabled TypeDAL, so the module-level classes stayed bound to the last
database created: cache rows and invalidations from one database went to
another, and `close()` on any database unbound them for all (#21).

Each TypeDAL now defines per-instance subclasses (same table names), and the
caching functions resolve them through `cache_models(db)` using the database
the query, row or hook belongs to. `close()` also leaves models alone that are
bound to a different database.

BREAKING CHANGE: `clear_cache`, `clear_expired`, `remove_cache` and
`remove_cache_for_table` take the database as first argument.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0181W827mjAmRu6ECjtQTU5v
Resolves the conflict in caching.py by keeping release/typedal-v6's
invalidation logic (table-wide invalidation for plain Sets, skipping empty
results) with the per-database `db` argument. Drops the module-global
binding workaround from `test_upsert_invalidates_cache`, which per-database
cache models make unnecessary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0181W827mjAmRu6ECjtQTU5v
Base automatically changed from release/typedal-v6 to master October 5, 2026 09:31
@robinvandernoord
robinvandernoord deleted the fix/per-db-cache-models branch October 5, 2026 09:31
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.

Cache models are module-global: a second TypeDAL rebinds them, and close() unbinds them for everyone

2 participants