storage: JSON files -> SQLite (users/history/searches/events)

- one-time import from the legacy JSON (left in place as snapshot);
  ghost rows (int vs str ep_id) deduped on import, unrepresentable after
- history POST is now an upsert: the (user, slug_id, ep_id) PK is the
  merge key, so the unguarded read-modify-write (lost updates) and the
  corruption-swallow (JSONDecodeError -> [] -> fresh overwrite) are gone
- searches: NOCASE PK upsert + cap 8
- events table + position/search logging (watch-time trajectory),
  90-day retention pruned at boot
- account delete cascades all four tables
- 22/22 tests green; old JSON files untouched
This commit is contained in:
jozamudi committed 2026-08-24 16:02:27 +00:00
1 parent 2c0ee8eae3
commit 202bfa41c3
5 files changed
+222 -105

No files matched your search

+10 -5
View File
@@ -54,13 +54,18 @@ def server():
data = Path(tempfile.mkdtemp(prefix="aniweb-test-"))
os.environ["ANIWEB_DATA"] = str(data)
sys.path.insert(0, str(ROOT))
from server import users # noqa: E402
from server import db, users # noqa: E402
db.init() # schema before users.add / seeding
for name, pw in USERS:
users.add(name, pw)
(data / "history").mkdir()
(data / "history" / "admin.json").write_text(json.dumps([
{"title": "Seed Anime", "slug_id": "seed-1", "season_id": 1, "ep_id": "1",
"lang": "eng", "ep": "1", "pos": 10.0, "t": time.time()}]))
c = db.connect()
seed_t = time.time()
c.execute("INSERT INTO history VALUES (?,?,?,?,?)",
("admin", "seed-1", 1, seed_t, json.dumps(
{"title": "Seed Anime", "slug_id": "seed-1", "season_id": 1,
"ep_id": 1, "lang": "eng", "ep": "1", "pos": 10.0, "t": seed_t})))
c.commit()
c.close()
proc = subprocess.Popen(
[sys.executable, "-m", "uvicorn", "server.app:app",