Feat: Add file logging to mvlog_worker.py

This commit is contained in:
hbrain 2026-05-27 06:35:56 +00:00
parent 6ba59cbfa7
commit e1f7c7b019

View file

@ -26,6 +26,7 @@ PUSH_CONFIG = Path.home() / ".config" / "mvlog" / "push.json"
STATE_NAME = ".movmaker-state.json" STATE_NAME = ".movmaker-state.json"
LOCK_NAME = ".movmaker-lock" LOCK_NAME = ".movmaker-lock"
ENABLED_NAME = ".movmaker-enabled" ENABLED_NAME = ".movmaker-enabled"
PREVIEW_NAME = ".movmaker-preview"
HIDDEN_NAME = ".mvlog-hidden" HIDDEN_NAME = ".mvlog-hidden"
NOTIFIED_CACHE = "cache/push_notifications.json" NOTIFIED_CACHE = "cache/push_notifications.json"
@ -74,7 +75,7 @@ entries = []
for dirpath, dirnames, filenames in os.walk(root): for dirpath, dirnames, filenames in os.walk(root):
dirnames[:] = [d for d in dirnames if d != '.movmaker-lock'] dirnames[:] = [d for d in dirnames if d != '.movmaker-lock']
for name in filenames: for name in filenames:
if name in {'.movmaker-state.json', '.movmaker-enabled', '.mvlog-hidden'}: if name in {'.movmaker-state.json', '.movmaker-enabled', '.movmaker-preview', '.mvlog-hidden'}:
continue continue
path = os.path.join(dirpath, name) path = os.path.join(dirpath, name)
rel = os.path.relpath(path, root) rel = os.path.relpath(path, root)
@ -214,9 +215,12 @@ def process_job(host: str, remote_root: str, job: str, work_dir: Path, extra_arg
job_dir = f"{remote_root}/in-dir/{job}" job_dir = f"{remote_root}/in-dir/{job}"
state = read_state(host, job_dir) state = read_state(host, job_dir)
maybe_send_first_show_notification(host, remote_root, job_dir, job, state) maybe_send_first_show_notification(host, remote_root, job_dir, job, state)
if not remote_file_exists(host, f"{job_dir}/{ENABLED_NAME}"): full_requested = remote_file_exists(host, f"{job_dir}/{ENABLED_NAME}")
preview_requested = remote_file_exists(host, f"{job_dir}/{PREVIEW_NAME}")
if not full_requested and not preview_requested:
print(f"disabled: {job}") print(f"disabled: {job}")
return return
preview_mode = preview_requested and not full_requested
if not acquire_lock(host, job_dir): if not acquire_lock(host, job_dir):
print(f"skip locked: {job}") print(f"skip locked: {job}")
return return
@ -224,17 +228,29 @@ def process_job(host: str, remote_root: str, job: str, work_dir: Path, extra_arg
fingerprint_before = remote_fingerprint(host, job_dir) fingerprint_before = remote_fingerprint(host, job_dir)
state = read_state(host, job_dir) state = read_state(host, job_dir)
old_output = state.get("output") if isinstance(state.get("output"), str) else None old_output = state.get("output") if isinstance(state.get("output"), str) else None
if not force and state.get("status") == "done" and state.get("fingerprint") == fingerprint_before and old_output: old_preview_output = state.get("preview_output") if isinstance(state.get("preview_output"), str) else None
if preview_mode:
if not force and state.get("preview_fingerprint") == fingerprint_before and old_preview_output:
if remote_file_exists(host, f"{remote_root}/out-dir/{old_preview_output}"):
print(f"preview up to date: {job} -> {old_preview_output}")
return
elif not force and state.get("status") == "done" and state.get("fingerprint") == fingerprint_before and old_output:
if remote_file_exists(host, f"{remote_root}/out-dir/{old_output}"): if remote_file_exists(host, f"{remote_root}/out-dir/{old_output}"):
print(f"up to date: {job} -> {old_output}") print(f"up to date: {job} -> {old_output}")
return return
write_state(host, job_dir, { processing_state = dict(state)
processing_state.update({
"status": "processing", "status": "processing",
"fingerprint": fingerprint_before, "mode": "preview" if preview_mode else "full",
"started_at": now(), "started_at": now(),
"output": old_output,
}) })
if preview_mode:
processing_state["preview_fingerprint"] = fingerprint_before
else:
processing_state["fingerprint"] = fingerprint_before
processing_state["output"] = old_output
write_state(host, job_dir, processing_state)
local_job = work_dir / job local_job = work_dir / job
if local_job.exists(): if local_job.exists():
@ -242,29 +258,56 @@ def process_job(host: str, remote_root: str, job: str, work_dir: Path, extra_arg
local_input = local_job / "input" local_input = local_job / "input"
local_out = local_job / "out" local_out = local_job / "out"
copy_job_from_remote(host, job_dir, local_input) copy_job_from_remote(host, job_dir, local_input)
print(f"rendering: {job}") render_args = [*extra_args, "--preview"] if preview_mode else extra_args
local_mp4 = render_job(local_input, local_out, extra_args) print(f"rendering {'preview: ' if preview_mode else ''}{job}")
local_mp4 = render_job(local_input, local_out, render_args)
if preview_mode:
preview_mp4 = local_mp4.with_name(f"{local_mp4.stem}_preview{local_mp4.suffix}")
local_mp4.rename(preview_mp4)
local_mp4 = preview_mp4
fingerprint_after = remote_fingerprint(host, job_dir) fingerprint_after = remote_fingerprint(host, job_dir)
if fingerprint_after != fingerprint_before: if fingerprint_after != fingerprint_before:
write_state(host, job_dir, { stale_state = dict(state)
stale_state.update({
"status": "stale", "status": "stale",
"fingerprint": fingerprint_after,
"previous_fingerprint": fingerprint_before,
"updated_at": now(), "updated_at": now(),
"message": "Input changed during render; will regenerate on next run.", "message": "Input changed during render; will regenerate on next run.",
"output": old_output,
}) })
if preview_mode:
stale_state["preview_fingerprint"] = fingerprint_after
stale_state["previous_preview_fingerprint"] = fingerprint_before
else:
stale_state["fingerprint"] = fingerprint_after
stale_state["previous_fingerprint"] = fingerprint_before
stale_state["output"] = old_output
write_state(host, job_dir, stale_state)
print(f"stale during render, not publishing: {job}") print(f"stale during render, not publishing: {job}")
return return
if preview_mode:
preview_output = publish_output(host, remote_root, local_mp4, old_preview_output)
new_state = dict(state)
new_state.update({
"status": "done",
"mode": "preview",
"preview_fingerprint": fingerprint_after,
"preview_output": preview_output,
"preview_generated_at": now(),
})
write_state(host, job_dir, new_state)
print(f"published preview: {job} -> {preview_output}")
return
output = publish_output(host, remote_root, local_mp4, old_output) output = publish_output(host, remote_root, local_mp4, old_output)
new_state = { new_state = dict(state)
new_state.update({
"status": "done", "status": "done",
"mode": "full",
"fingerprint": fingerprint_after, "fingerprint": fingerprint_after,
"output": output, "output": output,
"generated_at": now(), "generated_at": now(),
} })
maybe_send_first_show_notification(host, remote_root, job_dir, job, new_state) maybe_send_first_show_notification(host, remote_root, job_dir, job, new_state)
write_state(host, job_dir, new_state) write_state(host, job_dir, new_state)
print(f"published: {job} -> {output}") print(f"published: {job} -> {output}")