Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class TrackedSeries(Base):
rating = Column(String, nullable=True) # MangaBaka aggregated
mu_rating = Column(Float, nullable=True) # MangaUpdates bayesian rating (0-10)
mu_rating_votes = Column(Integer, nullable=True)
user_rating = Column(Float, nullable=True) # User's personal rating (0-10, integers)
user_rating = Column(Float, nullable=True) # User's personal rating (0-10, 0.5 increments)

# ── Chapter / release tracking ────────────────────────────────────
total_chapters = Column(String, nullable=True) # MB chapter count — unreliable per dev; last-resort fallback only
Expand Down
13 changes: 9 additions & 4 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,14 @@ def komga_import(req: KomgaImportRequest, background_tasks: BackgroundTasks):

@app.get("/api/komga/import/progress")
def komga_import_progress():
"""Poll this endpoint during a Komga import to show live progress."""
with _komga_import_lock:
return dict(_komga_import_progress)
"""Poll this endpoint during a Komga import to show live progress.

Deliberately does NOT acquire _komga_import_lock — the running import holds
that lock for its full duration, so taking it here would block every poll
until the import finished, defeating live progress. Reading the plain dict
is atomic enough for progress display.
"""
return dict(_komga_import_progress)


def _schedule_mu_lookup(background_tasks: BackgroundTasks, series_id: int, title: str):
Expand Down Expand Up @@ -482,7 +487,7 @@ def _do_lookup():
series.genres = json.dumps(merged)

# Authors
mu_authors = [a.get("name") for a in mu_data.get("authors", []) if a.get("name")]
mu_authors = [a.get("author_name") for a in mu_data.get("authors", []) if a.get("author_name")]
if mu_authors and not series.authors:
series.authors = json.dumps(mu_authors)

Expand Down
12 changes: 6 additions & 6 deletions app/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def _maybe_notify_poll_failure(db: "Session", series: TrackedSeries):
return
# Only fire at exact powers of 2 of the threshold to avoid spamming
ratio = failures // threshold
if ratio & (ratio - 1) != 0:
if (ratio & (ratio - 1)) != 0:
return
user_key, app_token, pushover_enabled = get_pushover_creds(db)
if not pushover_enabled or not user_key or not app_token:
Expand Down Expand Up @@ -1496,15 +1496,15 @@ def _poll_komga(db: Session, series_list: list[TrackedSeries]):

except KomgaAuthError:
logger.error("Komga: API key is invalid — check Settings")
# Mark all remaining Komga series as failed before breaking
for s in series_list:
_mark_poll_failure(s, "API key invalid", db)
# Global failure — mark only the current series; don't taint series
# already polled successfully this run. The rest are simply left for
# the next cycle rather than recorded as failures they never hit.
_mark_poll_failure(series, "API key invalid", db)
db.commit()
break
except KomgaConnectionError as e:
logger.error(f"Komga: server unreachable — {e}")
for s in series_list:
_mark_poll_failure(s, f"Server unreachable: {e}", db)
_mark_poll_failure(series, f"Server unreachable: {e}", db)
db.commit()
break
except KomgaNotFound:
Expand Down
Loading