fix: vid counter reuse and non-deterministic lookup in get_vid_folder
Two bugs caused vid number collisions (multiple files sharing a vid_NNN): 1. "First gap" assignment (n=1; while vid_n in existing: n++) would reuse deleted vid numbers. Changed to max(existing) + 1 so numbers always increase. 2. LIMIT 1 without ORDER BY returned arbitrary rows when a file had entries in multiple vid folders. Added ORDER BY rowid DESC for deterministic latest-wins behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+17
-11
@@ -423,22 +423,25 @@ class ProcessedDB:
|
|||||||
"""Return the vid_NNN folder name for a source video.
|
"""Return the vid_NNN folder name for a source video.
|
||||||
|
|
||||||
Checks existing DB output_paths first; if the video already has a
|
Checks existing DB output_paths first; if the video already has a
|
||||||
vid_NNN folder, returns it. Otherwise assigns the next available
|
vid_NNN folder, returns it. Otherwise assigns max(existing) + 1,
|
||||||
number, also checking disk for orphan vid folders.
|
also checking disk for orphan vid folders.
|
||||||
"""
|
"""
|
||||||
if not self._enabled:
|
if not self._enabled:
|
||||||
return "vid_001"
|
return "vid_001"
|
||||||
|
# Use the most recent entry (ORDER BY rowid DESC) for determinism
|
||||||
|
# when a file has entries across multiple vid folders.
|
||||||
row = self._con.execute(
|
row = self._con.execute(
|
||||||
"SELECT output_path FROM processed"
|
"SELECT output_path FROM processed"
|
||||||
" WHERE filename = ? AND profile = ? LIMIT 1",
|
" WHERE filename = ? AND profile = ?"
|
||||||
|
" ORDER BY rowid DESC LIMIT 1",
|
||||||
(filename, profile),
|
(filename, profile),
|
||||||
).fetchone()
|
).fetchone()
|
||||||
if row:
|
if row:
|
||||||
parent = os.path.basename(os.path.dirname(row[0]))
|
parent = os.path.basename(os.path.dirname(row[0]))
|
||||||
if parent.startswith("vid_"):
|
if parent.startswith("vid_"):
|
||||||
return parent
|
return parent
|
||||||
# Collect all existing vid_NNN names from DB + disk
|
# Collect max vid_NNN number from DB + disk (never reuse old numbers)
|
||||||
existing: set[str] = set()
|
max_n = 0
|
||||||
rows = self._con.execute(
|
rows = self._con.execute(
|
||||||
"SELECT DISTINCT output_path FROM processed WHERE profile = ?",
|
"SELECT DISTINCT output_path FROM processed WHERE profile = ?",
|
||||||
(profile,),
|
(profile,),
|
||||||
@@ -446,17 +449,20 @@ class ProcessedDB:
|
|||||||
for (op,) in rows:
|
for (op,) in rows:
|
||||||
p = os.path.basename(os.path.dirname(op))
|
p = os.path.basename(os.path.dirname(op))
|
||||||
if p.startswith("vid_"):
|
if p.startswith("vid_"):
|
||||||
existing.add(p)
|
try:
|
||||||
|
max_n = max(max_n, int(p.split("_")[1]))
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
pass
|
||||||
if os.path.isdir(export_folder):
|
if os.path.isdir(export_folder):
|
||||||
for d in os.listdir(export_folder):
|
for d in os.listdir(export_folder):
|
||||||
if d.startswith("vid_") and os.path.isdir(
|
if d.startswith("vid_") and os.path.isdir(
|
||||||
os.path.join(export_folder, d)
|
os.path.join(export_folder, d)
|
||||||
):
|
):
|
||||||
existing.add(d)
|
try:
|
||||||
n = 1
|
max_n = max(max_n, int(d.split("_")[1]))
|
||||||
while f"vid_{n:03d}" in existing:
|
except (IndexError, ValueError):
|
||||||
n += 1
|
pass
|
||||||
return f"vid_{n:03d}"
|
return f"vid_{max_n + 1:03d}"
|
||||||
|
|
||||||
def get_export_folders(self, profile: str = "default",
|
def get_export_folders(self, profile: str = "default",
|
||||||
include_scan_exports: bool = False) -> list[str]:
|
include_scan_exports: bool = False) -> list[str]:
|
||||||
|
|||||||
Reference in New Issue
Block a user