adds file locking
This commit is contained in:
@@ -13,6 +13,31 @@ video_extensions: list[str] = ["mp4", "mkv", "avi", "wmv", "mov", "m4v", "ts", "
|
||||
|
||||
total_files: int = 0
|
||||
|
||||
def acquire_file_lock(filepath: pathlib.Path) -> bool:
|
||||
lock_file = filepath.with_suffix(filepath.suffix + '.lock')
|
||||
try:
|
||||
# Atomic file creation
|
||||
lock_fd = os.open(str(lock_file), os.O_CREAT | os.O_EXCL | os.O_WRONLY)
|
||||
with os.fdopen(lock_fd, 'w') as f:
|
||||
f.write(f"{os.getpid()}\n{time.time()}\n")
|
||||
return True
|
||||
except FileExistsError:
|
||||
try:
|
||||
lock_age = time.time() - lock_file.stat().st_mtime
|
||||
if lock_age > 86400: # 24 hours
|
||||
lock_file.unlink()
|
||||
return acquire_file_lock(filepath)
|
||||
except FileNotFoundError:
|
||||
return acquire_file_lock(filepath)
|
||||
return False
|
||||
|
||||
def release_file_lock(filepath: pathlib.Path) -> None:
|
||||
lock_file = filepath.with_suffix(filepath.suffix + '.lock')
|
||||
try:
|
||||
lock_file.unlink()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def setup_logging(verbose: bool) -> None:
|
||||
"""Configure logging to both file and stdout."""
|
||||
log_level = logging.DEBUG if verbose else logging.INFO
|
||||
@@ -150,6 +175,10 @@ def process_single_file(
|
||||
nice: int,
|
||||
file_index: int
|
||||
) -> bool: # Return success/failure status
|
||||
if not acquire_file_lock(filepath):
|
||||
logging.info(f"Skipping {filepath}: already being processed")
|
||||
return False
|
||||
|
||||
temp_path = temp_dir / filepath.with_suffix(".mp4").name
|
||||
clean_directory(temp_dir) # Should be empty if mktemp was used, but clear it regardless.
|
||||
logging.info(f"Processing {filepath} to {target_path}")
|
||||
@@ -163,11 +192,13 @@ def process_single_file(
|
||||
logging.warning("Process interrupted by user")
|
||||
if temp_path.exists():
|
||||
temp_path.unlink()
|
||||
release_file_lock(filepath)
|
||||
raise # Re-raise KeyboardInterrupt to exit the program
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.error(f"FFmpeg error processing {filepath}: {e}")
|
||||
if temp_path.exists():
|
||||
temp_path.unlink()
|
||||
release_file_lock(filepath)
|
||||
return False
|
||||
else:
|
||||
# File successfully converted to av1, move to destination
|
||||
@@ -178,6 +209,7 @@ def process_single_file(
|
||||
if remove_source:
|
||||
logging.info(f"Removing source file {filepath}")
|
||||
filepath.unlink()
|
||||
release_file_lock(filepath)
|
||||
return True
|
||||
|
||||
def process_directory(
|
||||
|
||||
Reference in New Issue
Block a user