feature/bookstate-progress-fix
peter.fong 4 days ago
parent fa2f212e03
commit 516bca6de5

@ -299,3 +299,58 @@ def inc_parsed(book_idx, amount=1):
@logcall
def inc_audio_done_legacy(book_idx, amount=1):
return inc_audio_done(book_idx, amount)
# ============================================================
# READ — DERIVED BOOK STATE
# ============================================================
@logcall
def get_book_state(book_idx):
"""
Canonical read-model for a single book.
Responsibilities:
- Read SQLite snapshot (static metadata)
- Read Redis live state (counters / status)
- Compute derived fields (NO UI logic)
Invariants:
- downloaded = chapters_download_done + chapters_download_skipped
"""
# --- SQLite snapshot ---
sqlite_row = sql_fetch_book(book_idx) or {}
# --- Redis live state ---
key = f"book:{book_idx}:state"
redis_state = _r.hgetall(key) or {}
# Normalize numeric redis values
def _int(v):
try:
return int(v)
except Exception:
return 0
# --- primary counters ---
chapters_done = _int(redis_state.get("chapters_download_done"))
chapters_skipped = _int(redis_state.get("chapters_download_skipped"))
# --- derived counters ---
downloaded = chapters_done + chapters_skipped
# --- build canonical state ---
state = {}
# 1) start with SQLite snapshot
state.update(sqlite_row)
# 2) overlay Redis live fields
state.update(redis_state)
# 3) enforce derived invariants
state["downloaded"] = downloaded
return state

@ -46,7 +46,7 @@ def _build_card(sqlite_row, redis_state, merged):
# ============================================================
# INSPECT ONLY — NO WRITES
# ============================================================
def inspect_books_state():
def inspect_books_state_depecrated():
"""
Reads all books from SQLite and fetches Redis progress.
Builds:
@ -121,6 +121,88 @@ def inspect_books_state():
return results
# ============================================================
# INSPECT ONLY — NO WRITES
# ============================================================
def inspect_books_state():
"""
Reads canonical book state from repository.
Builds:
entry.sqlite
entry.redis
entry.would_merge_to
entry.card (book-card compatible)
"""
from db.repository import get_book_state
from db.db import get_db
db = get_db()
cur = db.cursor()
# Alleen nodig om te weten *welke* books er zijn
cur.execute("SELECT book_idx FROM books")
rows = cur.fetchall()
results = []
for row in rows:
book_idx = row["book_idx"]
# --------------------------------
# Canonical state (ENIGE waarheid)
# --------------------------------
state = get_book_state(book_idx)
# SQLite-view = alleen SQLite-kolommen
sqlite_view = {
k: v
for k, v in state.items()
if k
in (
"book_idx",
"title",
"author",
"description",
"cover_path",
"book_url",
"chapters_total",
"status",
"downloaded",
"parsed",
"audio_done",
"created_at",
"processdate",
"last_update",
)
}
# Redis-view = alleen Redis counters/status
redis_view = {
k: v
for k, v in state.items()
if k.startswith("chapters_")
or k in ("status", "audio_done", "audio_skipped")
}
merged = state # letterlijk de canonieke state
card = _build_card(sqlite_view, redis_view, merged)
results.append(
{
"book_idx": book_idx,
"title": state.get("title"),
"sqlite": sqlite_view,
"redis": redis_view,
"would_merge_to": merged,
"card": card,
}
)
return results
# ============================================================
# SYNC REDIS → SQLITE (writes)
# ============================================================

@ -93,9 +93,10 @@ function updateButtons(card, state) {
function updateProgress(card, s) {
const total = Number(s.chapters_total || 0);
const downloadDone =
Number(s.chapters_download_done || 0) +
Number(s.chapters_download_skipped || 0);
// const downloadDone =
// Number(s.chapters_download_done || 0) +
// Number(s.chapters_download_skipped || 0);
const downloadDone = Number(s.downloaded || 0);
const audioDone = Number(s.audio_done || 0) + Number(s.audio_skipped || 0);

Loading…
Cancel
Save