fix: stop scan crashing on duplicate file hashes
scan.py used scalar_one_or_none() to test whether any other photo shared the same file_hash, but that helper raises MultipleResultsFound the moment 2+ rows match — i.e. exactly the duplicate case it was trying to flag. Every file beyond the second copy bombed out with "Multiple rows were found when one or none was required" and was left in the failed bucket. Replace with a COUNT(*) > 0 check. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ import json
|
|||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
|
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select, func
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
import aiofiles
|
import aiofiles
|
||||||
import redis
|
import redis
|
||||||
@@ -172,10 +172,21 @@ async def _scan_folder_async(folder_path: str, source_root_id: Optional[str], ta
|
|||||||
# Calculate file hash for duplicate detection
|
# Calculate file hash for duplicate detection
|
||||||
file_hash = await calculate_file_hash(filepath)
|
file_hash = await calculate_file_hash(filepath)
|
||||||
|
|
||||||
# Check for duplicate by hash
|
# Check for duplicate by hash. We only care
|
||||||
duplicate = await session.execute(
|
# whether *any* other photo shares this hash, so
|
||||||
select(Photo).where(Photo.file_hash == file_hash)
|
# use a count rather than scalar_one_or_none()
|
||||||
) if file_hash else None
|
# which raises "Multiple rows were found" the
|
||||||
|
# moment the library has 2+ copies of the same
|
||||||
|
# file (i.e. exactly the case we're trying to
|
||||||
|
# flag).
|
||||||
|
is_dup = False
|
||||||
|
if file_hash:
|
||||||
|
dup_count = (await session.execute(
|
||||||
|
select(func.count(Photo.id)).where(
|
||||||
|
Photo.file_hash == file_hash
|
||||||
|
)
|
||||||
|
)).scalar() or 0
|
||||||
|
is_dup = dup_count > 0
|
||||||
|
|
||||||
# Create photo entry
|
# Create photo entry
|
||||||
photo = Photo(
|
photo = Photo(
|
||||||
@@ -188,7 +199,7 @@ async def _scan_folder_async(folder_path: str, source_root_id: Optional[str], ta
|
|||||||
file_size=stat.st_size,
|
file_size=stat.st_size,
|
||||||
taken_at=datetime.fromtimestamp(stat.st_mtime),
|
taken_at=datetime.fromtimestamp(stat.st_mtime),
|
||||||
taken_at_source='filesystem',
|
taken_at_source='filesystem',
|
||||||
is_duplicate=bool(duplicate.scalar_one_or_none() if duplicate else False),
|
is_duplicate=is_dup,
|
||||||
processing_status='pending'
|
processing_status='pending'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user