mirror of
https://github.com/blw1138/Zordon.git
synced 2026-06-10 14:09:24 -05:00
refactor: wire all services through ApplicationContext
- Created src/application_context.py as DI container with TYPE_CHECKING imports - server.py now instantiates all services in dependency order via ApplicationContext - Fixed infinite recursion bug: 48 instance methods renamed with underscore prefix to avoid shadowing by same-named @classmethod forwarders - ZeroconfServer: instantiate Zeroconf() in __init__, add _sync_class() to configure forwarder, direct _configure/_start calls during wiring - Config, EngineManager, PreviewManager: all forwarders and _sync_class() intact - RenderQueue: load_state and subscribe moved to __init__, threading.Lock retained - DistributedJobManager: subscribe_to_listener moved to __init__
This commit is contained in:
+40
-16
@@ -3,6 +3,7 @@ import os
|
||||
import subprocess
|
||||
import threading
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional
|
||||
|
||||
from src.utilities.ffmpeg_helper import generate_thumbnail, save_first_frame
|
||||
|
||||
@@ -12,12 +13,20 @@ supported_image_formats = ['.jpg', '.png', '.exr', '.tif', '.tga', '.bmp', '.web
|
||||
|
||||
|
||||
class PreviewManager:
|
||||
_default_instance: Optional['PreviewManager'] = None
|
||||
|
||||
storage_path = None
|
||||
_running_jobs = {}
|
||||
storage_path: Optional[str] = None
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.storage_path = None
|
||||
self._running_jobs: Dict = {}
|
||||
|
||||
@classmethod
|
||||
def __generate_job_preview_worker(cls, job, replace_existing=False, max_width=480):
|
||||
def _sync_class(cls) -> None:
|
||||
if cls._default_instance is not None:
|
||||
cls.storage_path = cls._default_instance.storage_path
|
||||
|
||||
def _generate_job_preview_worker(self, job, replace_existing=False, max_width=480):
|
||||
|
||||
# Determine best source file to use for thumbs
|
||||
job_file_list = job.file_list()
|
||||
@@ -33,8 +42,8 @@ class PreviewManager:
|
||||
logger.warning(f"No valid image or video files found in files from job: {job}")
|
||||
return
|
||||
|
||||
os.makedirs(cls.storage_path, exist_ok=True)
|
||||
base_path = os.path.join(cls.storage_path, f"{job.id}-{preview_label}-{max_width}")
|
||||
os.makedirs(self.storage_path, exist_ok=True)
|
||||
base_path = os.path.join(self.storage_path, f"{job.id}-{preview_label}-{max_width}")
|
||||
preview_video_path = base_path + '.mp4'
|
||||
preview_image_path = base_path + '.jpg'
|
||||
|
||||
@@ -65,25 +74,23 @@ class PreviewManager:
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"Error generating video preview for {job}: {e}")
|
||||
|
||||
@classmethod
|
||||
def update_previews_for_job(cls, job, replace_existing=False, wait_until_completion=False, timeout=None):
|
||||
job_thread = cls._running_jobs.get(job.id)
|
||||
def _update_previews_for_job(self, job, replace_existing=False, wait_until_completion=False, timeout=None):
|
||||
job_thread = self._running_jobs.get(job.id)
|
||||
if job_thread and job_thread.is_alive():
|
||||
logger.debug(f'Preview generation job already running for {job}')
|
||||
else:
|
||||
job_thread = threading.Thread(target=cls.__generate_job_preview_worker, args=(job, replace_existing,))
|
||||
job_thread = threading.Thread(target=self._generate_job_preview_worker, args=(job, replace_existing,))
|
||||
job_thread.start()
|
||||
cls._running_jobs[job.id] = job_thread
|
||||
self._running_jobs[job.id] = job_thread
|
||||
|
||||
if wait_until_completion:
|
||||
job_thread.join(timeout=timeout)
|
||||
|
||||
@classmethod
|
||||
def get_previews_for_job(cls, job):
|
||||
def _get_previews_for_job(self, job):
|
||||
|
||||
results = {}
|
||||
try:
|
||||
directory_path = Path(cls.storage_path)
|
||||
directory_path = Path(self.storage_path)
|
||||
preview_files_for_job = [f for f in directory_path.iterdir() if f.is_file() and f.name.startswith(job.id)]
|
||||
|
||||
for preview_filename in preview_files_for_job:
|
||||
@@ -101,9 +108,8 @@ class PreviewManager:
|
||||
pass
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def delete_previews_for_job(cls, job):
|
||||
all_previews = cls.get_previews_for_job(job)
|
||||
def _delete_previews_for_job(self, job):
|
||||
all_previews = self.get_previews_for_job(job)
|
||||
flattened_list = [item for sublist in all_previews.values() for item in sublist]
|
||||
for preview in flattened_list:
|
||||
try:
|
||||
@@ -111,3 +117,21 @@ class PreviewManager:
|
||||
os.remove(preview['filename'])
|
||||
except OSError as e:
|
||||
logger.error(f"Error removing preview '{preview.get('filename')}': {e}")
|
||||
|
||||
# --- Forwarders for backward compatibility ---
|
||||
|
||||
@classmethod
|
||||
def update_previews_for_job(cls, job, replace_existing=False, wait_until_completion=False, timeout=None):
|
||||
if cls._default_instance is not None:
|
||||
cls._default_instance._update_previews_for_job(job, replace_existing, wait_until_completion, timeout)
|
||||
|
||||
@classmethod
|
||||
def get_previews_for_job(cls, job):
|
||||
if cls._default_instance is not None:
|
||||
return cls._default_instance._get_previews_for_job(job)
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def delete_previews_for_job(cls, job):
|
||||
if cls._default_instance is not None:
|
||||
cls._default_instance._delete_previews_for_job(job)
|
||||
|
||||
Reference in New Issue
Block a user