correcting accidental isses
This commit is contained in:
@@ -305,3 +305,147 @@ def do_thumbnail_regen() -> None:
|
|||||||
db.session.expunge_all()
|
db.session.expunge_all()
|
||||||
|
|
||||||
bt = time.time() - bt0
|
bt = time.time() - bt0
|
||||||
|
rate = batch_processed / bt if bt > 0 else 0
|
||||||
|
log.info(
|
||||||
|
"[Thumbs] Batch %s-%s: processed=%d writes=%d db_updates=%d failures=%d (%.1f items/s) "
|
||||||
|
"— totals: processed=%d writes=%d db_updates=%d failures=%d (last_id=%d)",
|
||||||
|
batch_start_id,
|
||||||
|
batch_end_id,
|
||||||
|
batch_processed,
|
||||||
|
batch_writes,
|
||||||
|
batch_updates,
|
||||||
|
batch_failures,
|
||||||
|
rate,
|
||||||
|
processed,
|
||||||
|
writes,
|
||||||
|
path_updates,
|
||||||
|
failures,
|
||||||
|
last_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
elapsed = time.time() - t_start
|
||||||
|
overall_rate = processed / elapsed if elapsed > 0 else 0
|
||||||
|
log.info(
|
||||||
|
"[Thumbs] COMPLETE in %.1fs — processed=%d writes=%d db_updates=%d failures=%d (%.1f items/s).",
|
||||||
|
elapsed,
|
||||||
|
processed,
|
||||||
|
writes,
|
||||||
|
path_updates,
|
||||||
|
failures,
|
||||||
|
overall_rate,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Orchestration helpers
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
def handle_flag_job(
|
||||||
|
job: FlagJob,
|
||||||
|
fn: Callable[[], None],
|
||||||
|
*,
|
||||||
|
dispose_engine_on_operational_error: bool = False,
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
If <flag> exists, claim it and run fn with retries.
|
||||||
|
Returns True if it did anything (including another worker claiming it).
|
||||||
|
"""
|
||||||
|
if not os.path.exists(job.flag_path):
|
||||||
|
return False
|
||||||
|
|
||||||
|
log.info("[%s] Flag detected: %s", job.name, job.flag_path)
|
||||||
|
|
||||||
|
if not claim_job(job):
|
||||||
|
# It existed, but someone else may have claimed it.
|
||||||
|
return True
|
||||||
|
|
||||||
|
ok, err_text = run_with_retries(
|
||||||
|
job,
|
||||||
|
fn,
|
||||||
|
dispose_engine_on_operational_error=dispose_engine_on_operational_error,
|
||||||
|
)
|
||||||
|
if ok:
|
||||||
|
complete_job(job)
|
||||||
|
else:
|
||||||
|
fail_job(job, error_text=err_text)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Main loop
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
def monitor_and_import() -> None:
|
||||||
|
thumbnail_job = FlagJob(name="Thumbs", flag_path=THUMBNAIL_FLAG)
|
||||||
|
import_job = FlagJob(name="Import", flag_path=TRIGGER_FLAG)
|
||||||
|
|
||||||
|
# next time we should run periodic import (monotonic avoids wall-clock jumps)
|
||||||
|
next_periodic_import = time.monotonic() + IMPORT_EVERY_SECONDS
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
log.info(
|
||||||
|
"[Worker] Started. Poll=%ss, periodic import every=%ss (%.2fh).",
|
||||||
|
CHECK_INTERVAL,
|
||||||
|
IMPORT_EVERY_SECONDS,
|
||||||
|
IMPORT_EVERY_SECONDS / 3600.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
did_work = False
|
||||||
|
|
||||||
|
# 1) Thumbnail regen (priority)
|
||||||
|
did_work |= handle_flag_job(thumbnail_job, do_thumbnail_regen)
|
||||||
|
|
||||||
|
# 2) Flag-triggered import
|
||||||
|
did_work |= handle_flag_job(
|
||||||
|
import_job,
|
||||||
|
do_import,
|
||||||
|
dispose_engine_on_operational_error=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3) Periodic import (every IMPORT_EVERY_SECONDS)
|
||||||
|
now = time.monotonic()
|
||||||
|
if IMPORT_EVERY_SECONDS > 0 and now >= next_periodic_import:
|
||||||
|
next_periodic_import = now + IMPORT_EVERY_SECONDS
|
||||||
|
|
||||||
|
# Skip if an import is already in progress or in error
|
||||||
|
if os.path.exists(import_job.run_path):
|
||||||
|
log.info("[Import] Periodic run skipped (import already running).")
|
||||||
|
elif os.path.exists(import_job.err_path):
|
||||||
|
log.info(
|
||||||
|
"[Import] Periodic run skipped (import in error state: %s).",
|
||||||
|
import_job.err_path,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Create a .run lock for periodic run (no trigger.flag required)
|
||||||
|
tmp = import_job.run_path + ".tmp"
|
||||||
|
try:
|
||||||
|
with open(tmp, "w", encoding="utf-8") as f:
|
||||||
|
f.write("periodic\n")
|
||||||
|
os.replace(tmp, import_job.run_path)
|
||||||
|
log.info("[Import] Periodic run claimed -> %s", import_job.run_path)
|
||||||
|
|
||||||
|
ok, err_text = run_with_retries(
|
||||||
|
import_job,
|
||||||
|
do_import,
|
||||||
|
dispose_engine_on_operational_error=True,
|
||||||
|
)
|
||||||
|
if ok:
|
||||||
|
complete_job(import_job)
|
||||||
|
else:
|
||||||
|
fail_job(import_job, error_text=err_text)
|
||||||
|
|
||||||
|
did_work = True
|
||||||
|
except Exception as e:
|
||||||
|
log.warning("[Import] Could not start periodic run: %s", e)
|
||||||
|
try:
|
||||||
|
if os.path.exists(tmp):
|
||||||
|
os.remove(tmp)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not did_work:
|
||||||
|
time.sleep(CHECK_INTERVAL)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
monitor_and_import()
|
||||||
|
|||||||
Reference in New Issue
Block a user