""" WatchService - сервис отслеживания файлов с очередью """ import time import threading import queue from pathlib import Path from typing import Callable, Optional from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler from services.file_service import FileService class PhotoHandler(FileSystemEventHandler): """Обработчик событий файловой системы""" def __init__(self, callback: Callable[[Path], None]): self.callback = callback self._pending_files = queue.Queue() self._processing = True self._processor_thread = threading.Thread(target=self._process_queue, daemon=True) self._processor_thread.start() def on_created(self, event): if not event.is_directory: src_path = Path(event.src_path) if FileService.is_photo(src_path): time.sleep(0.1) # Даём время на запись файла self._pending_files.put(src_path) def _process_queue(self): while self._processing: try: file_path = self._pending_files.get(timeout=1) if self.callback and file_path.exists(): self.callback(file_path) except queue.Empty: continue except Exception as e: print(f"Ошибка обработки файла: {e}") def stop(self): self._processing = False class WatchService: """Сервис для отслеживания папки на новые файлы""" def __init__(self): self._observer: Optional[Observer] = None self._event_handler: Optional[PhotoHandler] = None self._is_running = False def start(self, watch_folder: Path, on_new_file: Callable[[Path], None]) -> bool: if self._is_running: return False if not watch_folder.exists(): return False try: self._event_handler = PhotoHandler(on_new_file) self._observer = Observer() self._observer.schedule(self._event_handler, str(watch_folder), recursive=False) self._observer.start() self._is_running = True return True except Exception as e: print(f"Ошибка запуска отслеживания: {e}") return False def stop(self): if self._observer: self._observer.stop() self._observer.join() self._observer = None if self._event_handler: self._event_handler.stop() self._event_handler = None self._is_running = False def is_running(self) -> bool: return self._is_running def move_all_existing_files(self, watch_folder: Path, on_file_moved: Callable[[Path], None]) -> int: """Перемещает все существующие файлы""" count = 0 if watch_folder.exists(): for file_path in watch_folder.iterdir(): if file_path.is_file() and FileService.is_photo(file_path): try: on_file_moved(file_path) count += 1 time.sleep(0.05) except Exception as e: print(f"Ошибка перемещения {file_path.name}: {e}") return count