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
7 changes: 1 addition & 6 deletions backend/api/instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -1681,12 +1681,7 @@ async def get_instance_stats(
else:
# Count rows cheaply rather than loading the whole library to len()
# it (a Lidarr instance is tens of thousands of rows).
row = db.media.execute_query(
"SELECT COUNT(*) AS n FROM media_cache WHERE instance_name=?",
(instance_id,),
fetch_one=True,
)
total = row["n"] if row else 0
total = db.media.count_by_instance(instance_id)
# ARR freshness comes from sync_state (written when the ARR sync
# completes), not media_cache.updated_at — the latter only moves on
# changed rows, so it would read "stale" right after a fresh sync of
Expand Down
14 changes: 3 additions & 11 deletions backend/api/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,20 +142,12 @@ async def list_webhook_origins(
Summarize webhook jobs in the last N days by origin (client_host + endpoint)
and status. Helpful for spotting a noisy Sonarr instance or a dead webhook.
"""
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone

try:
days = max(1, min(days, 90))
cutoff = (datetime.utcnow() - timedelta(days=days)).isoformat()
rows = (
db.worker.execute_query(
"SELECT id, payload, status, received_at FROM jobs "
"WHERE type='webhook' AND received_at >= ? ORDER BY received_at DESC",
(cutoff,),
fetch_all=True,
)
or []
)
cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
rows = db.worker.jobs_of_type_since("webhook", cutoff)
from collections import Counter

by_origin: Counter = Counter()
Expand Down
8 changes: 4 additions & 4 deletions backend/api/media_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1709,10 +1709,10 @@ async def update_media_metadata(

# Audit trail: capture each field's old→new so reverts and diffs
# are possible later without having to replay the whole edit stream.
from datetime import datetime as _dt
from datetime import datetime as _dt, timezone as _tz

edited_by = getattr(request.state, "user", "") or "unknown"
now_iso = _dt.utcnow().isoformat()
now_iso = _dt.now(_tz.utc).isoformat()
for field, new_value in update_kwargs.items():
old_value = item.get(field)
if old_value == new_value:
Expand Down Expand Up @@ -2000,9 +2000,9 @@ async def generate_collection_from_tag(
{"created": False, "matched_media": len(media_rows)},
)

from datetime import datetime as _dt
from datetime import datetime as _dt, timezone as _tz

created_at = _dt.utcnow().isoformat()
created_at = _dt.now(_tz.utc).isoformat()
coll_id = db.poster.create_collection(
name, f"Auto-generated from tag '{tag}'", created_at
)
Expand Down
11 changes: 7 additions & 4 deletions backend/api/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -1289,10 +1289,13 @@ async def cancel_module_execution(
if request_cancellation(job_id):
# Update job status to reflect cancellation is in progress
now = datetime.now(timezone.utc).isoformat()
db.worker.execute_query(
"UPDATE jobs SET status='cancelled', completed_at=? WHERE id=? AND status='running'",
(now, job_id),
)
# 0 rows means it stopped running between the check above and here.
if not db.worker.cancel_running_job(job_id, now):
return error(
f"Job {job_id} finished before it could be cancelled",
code="JOB_NOT_RUNNING",
status_code=409,
)
logger.info(f"Cancellation requested for module {name} job {job_id}")
return ok(
f"Cancellation requested for module {name} job {job_id}",
Expand Down
Loading