Add pragmas, hard_reset, and vacuum for tuning disk-backed caches
This commit is contained in:
@@ -168,3 +168,123 @@ def test_disk_mode_reset_keeps_file(tmp_path, source_conn):
|
||||
assert db_path.exists()
|
||||
assert c.is_table_cached("users") is False
|
||||
c.close()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pragmas / layout tuning (1.11.0)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_pragmas_applied_on_fresh_disk_cache(tmp_path):
|
||||
"""page_size, auto_vacuum and a generic pragma all take effect on a new file."""
|
||||
c = CacheManager(
|
||||
db_path=tmp_path / "cache.db",
|
||||
backup_interval=9999,
|
||||
in_memory=False,
|
||||
pragmas={"page_size": 8192, "auto_vacuum": "INCREMENTAL", "cache_size": -2000},
|
||||
)
|
||||
assert c.connection.execute("PRAGMA page_size").fetchone()[0] == 8192
|
||||
assert c.connection.execute("PRAGMA auto_vacuum").fetchone()[0] == 2 # INCREMENTAL
|
||||
assert c.connection.execute("PRAGMA cache_size").fetchone()[0] == -2000
|
||||
c.close()
|
||||
|
||||
|
||||
def test_page_size_ignored_on_existing_file_warns(tmp_path):
|
||||
"""A page_size that differs from the existing file is ignored, with a warning."""
|
||||
db_path = tmp_path / "cache.db"
|
||||
c1 = CacheManager(db_path=db_path, backup_interval=9999, in_memory=False)
|
||||
assert c1.connection.execute("PRAGMA page_size").fetchone()[0] == 4096 # default
|
||||
c1.close()
|
||||
|
||||
c2 = CacheManager(
|
||||
db_path=db_path,
|
||||
backup_interval=9999,
|
||||
in_memory=False,
|
||||
pragmas={"page_size": 16384},
|
||||
)
|
||||
# File keeps its original page size; the request is ignored (not an error).
|
||||
assert c2.connection.execute("PRAGMA page_size").fetchone()[0] == 4096
|
||||
c2.close()
|
||||
|
||||
|
||||
def test_unknown_pragma_does_not_crash(tmp_path):
|
||||
"""SQLite ignores unknown/inapplicable pragmas — startup must not fail."""
|
||||
c = CacheManager(
|
||||
db_path=tmp_path / "cache.db",
|
||||
backup_interval=9999,
|
||||
in_memory=False,
|
||||
pragmas={"this_is_not_a_pragma": 1, "mmap_size": 1024 * 1024},
|
||||
)
|
||||
assert c.connection.execute("PRAGMA mmap_size").fetchone()[0] == 1024 * 1024
|
||||
c.close()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# hard_reset / vacuum (1.11.0)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_hard_reset_recreates_file_and_clears_tables(tmp_path, source_conn):
|
||||
db_path = tmp_path / "cache.db"
|
||||
c = CacheManager(db_path=db_path, backup_interval=9999, in_memory=False)
|
||||
c.load_table("users", ["name"], source_conn)
|
||||
assert c.is_table_cached("users") is True
|
||||
|
||||
c.hard_reset()
|
||||
assert db_path.exists() # reopened fresh
|
||||
assert c.is_table_cached("users") is False
|
||||
# The connection is usable again after the swap.
|
||||
c.load_table("users", ["name"], source_conn)
|
||||
assert c.is_table_cached("users") is True
|
||||
c.close()
|
||||
|
||||
|
||||
def test_hard_reset_applies_new_page_size(tmp_path, source_conn):
|
||||
"""page_size can't change via reset() but does via hard_reset() (fresh file)."""
|
||||
db_path = tmp_path / "cache.db"
|
||||
# Existing file at the default 4096; request 8192 — ignored on open.
|
||||
CacheManager(db_path=db_path, backup_interval=9999, in_memory=False).close()
|
||||
c = CacheManager(
|
||||
db_path=db_path,
|
||||
backup_interval=9999,
|
||||
in_memory=False,
|
||||
pragmas={"page_size": 8192},
|
||||
)
|
||||
assert c.connection.execute("PRAGMA page_size").fetchone()[0] == 4096
|
||||
c.hard_reset() # deletes the file → recreated with the requested page size
|
||||
assert c.connection.execute("PRAGMA page_size").fetchone()[0] == 8192
|
||||
c.close()
|
||||
|
||||
|
||||
def test_hard_reset_in_memory_falls_back_to_reset(tmp_path, source_conn):
|
||||
c = CacheManager(db_path=tmp_path / "cache.db", backup_interval=9999)
|
||||
c.load_table("users", ["name"], source_conn)
|
||||
c.hard_reset() # memory mode → reset()
|
||||
assert c.is_table_cached("users") is False
|
||||
c.close()
|
||||
|
||||
|
||||
def test_full_vacuum_runs_on_disk(tmp_path, source_conn):
|
||||
db_path = tmp_path / "cache.db"
|
||||
c = CacheManager(db_path=db_path, backup_interval=9999, in_memory=False)
|
||||
c.load_table("users", ["name"], source_conn)
|
||||
c.vacuum(incremental=False) # must not raise
|
||||
assert c.is_table_cached("users") is True
|
||||
c.close()
|
||||
|
||||
|
||||
def test_incremental_vacuum_runs_with_auto_vacuum(tmp_path, source_conn):
|
||||
c = CacheManager(
|
||||
db_path=tmp_path / "cache.db",
|
||||
backup_interval=9999,
|
||||
in_memory=False,
|
||||
pragmas={"auto_vacuum": "INCREMENTAL"},
|
||||
)
|
||||
c.load_table("users", ["name"], source_conn)
|
||||
c.vacuum(incremental=True, pages=100) # must not raise
|
||||
assert c.is_table_cached("users") is True
|
||||
c.close()
|
||||
|
||||
|
||||
def test_vacuum_in_memory_is_noop(cache, source_conn):
|
||||
cache.load_table("users", ["name"], source_conn)
|
||||
cache.vacuum(incremental=False) # no-op, no error
|
||||
assert cache.is_table_cached("users") is True
|
||||
|
||||
@@ -385,3 +385,39 @@ def test_two_engines_separate_cache_files(source_engine, tmp_path):
|
||||
assert b._cache.is_table_cached("products") is False # independent cache
|
||||
a.close()
|
||||
b.close()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pragmas / hard_reset / vacuum (1.11.0)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_engine_passes_pragmas_to_cache(source_engine, tmp_path):
|
||||
ce = CachingEngine(
|
||||
source_engine,
|
||||
cache_db_path=tmp_path / "cache.db",
|
||||
in_memory=False,
|
||||
pragmas={"page_size": 8192, "auto_vacuum": "INCREMENTAL"},
|
||||
)
|
||||
assert ce._cache.connection.execute("PRAGMA page_size").fetchone()[0] == 8192
|
||||
assert ce._cache.connection.execute("PRAGMA auto_vacuum").fetchone()[0] == 2
|
||||
ce.close()
|
||||
|
||||
|
||||
def test_engine_hard_reset_reloads(source_engine, tmp_path):
|
||||
ce = CachingEngine(source_engine, cache_db_path=tmp_path / "cache.db", in_memory=False)
|
||||
ce.execute("SELECT id FROM products")
|
||||
assert ce._cache.is_table_cached("products") is True
|
||||
|
||||
ce.hard_reset()
|
||||
assert ce._cache.is_table_cached("products") is False
|
||||
rows = ce.execute("SELECT id, name FROM products") # reloads on next use
|
||||
assert len(rows) == 3
|
||||
ce.close()
|
||||
|
||||
|
||||
def test_engine_vacuum_runs(source_engine, tmp_path):
|
||||
ce = CachingEngine(source_engine, cache_db_path=tmp_path / "cache.db", in_memory=False)
|
||||
ce.execute("SELECT id FROM products")
|
||||
ce.vacuum(incremental=False) # must not raise
|
||||
assert ce._cache.is_table_cached("products") is True
|
||||
ce.close()
|
||||
|
||||
Reference in New Issue
Block a user