Files
upstream-aw-core/tests/test_peewee.py
upstream-mirror 8757f2fd5e
Some checks failed
Build / Test on ubuntu-latest, py-3.8 (push) Successful in 4m21s
Lint / lint (push) Successful in 25s
Build / Test on macOS-latest, py-3.8 (push) Has been cancelled
Build / Test on windows-latest, py-3.8 (push) Has been cancelled
CodeQL / Analyze (python) (push) Failing after 1s
snapshot of https://github.com/ActivityWatch/aw-core.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 00:17:07 +05:00

67 lines
2.3 KiB
Python

"""
Peewee-storage-specific tests, mainly for the schema/index migration in
auto_migrate() and for guarding against query-plan regressions.
"""
import logging
from aw_datastore.storages import PeeweeStorage
from aw_datastore.storages import peewee as peewee_storage
from . import context # noqa: F401
logging.basicConfig(level=logging.DEBUG)
def _indexes(db) -> set:
return {row[1] for row in db.execute_sql("PRAGMA index_list(eventmodel)")}
def test_index_migration():
"""auto_migrate() replaces the old single-column indexes with the composite one."""
storage = PeeweeStorage(testing=True)
db = storage.db
path = db.database
assert "eventmodel_bucket_id_timestamp" in _indexes(db)
# Recreate the pre-migration state: single-column indexes, no composite
db.execute_sql("DROP INDEX eventmodel_bucket_id_timestamp")
db.execute_sql("CREATE INDEX eventmodel_bucket_id ON eventmodel (bucket_id)")
db.execute_sql("CREATE INDEX eventmodel_timestamp ON eventmodel (timestamp)")
peewee_storage.auto_migrate(path)
indexes = _indexes(db)
assert "eventmodel_bucket_id_timestamp" in indexes
assert "eventmodel_bucket_id" not in indexes
assert "eventmodel_timestamp" not in indexes
def test_query_plan_uses_composite_index():
"""
The last-event query (issued by replace_last on every merged heartbeat) and
range queries must be served by the composite index in a single pass.
Without it, SQLite reads *all* of a bucket's rows and sorts them in a temp
B-tree even for LIMIT 1, which on multi-million-event buckets meant seconds
of CPU/IO per heartbeat (and terabytes read per day).
"""
storage = PeeweeStorage(testing=True)
db = storage.db
queries = [
# replace_last/_get_last
"SELECT * FROM eventmodel WHERE bucket_id = 1"
" ORDER BY timestamp DESC LIMIT 1",
# get_events with a time range
"SELECT * FROM eventmodel WHERE bucket_id = 1"
" AND timestamp >= '2026-01-01' AND timestamp <= '2026-01-02'"
" ORDER BY timestamp DESC LIMIT 100",
]
for query in queries:
rows = db.execute_sql(f"EXPLAIN QUERY PLAN {query}").fetchall()
plan = "\n".join(str(row) for row in rows)
assert "eventmodel_bucket_id_timestamp" in plan, plan
assert "TEMP B-TREE" not in plan, plan