fix(vision): reference image sopravvive al copy-on-write (#38.6)
_copy_tasks_to_version non copiava le righe VisionReferenceImage del task sorgente: il task copiato perdeva le immagini di riferimento del grafo di visione. Ora copia le righe sul task nuovo, stesso path e stessi metadati (stesso file su disco, non duplicato). Di conseguenza il file va cancellato solo se nessun'altra riga VisionReferenceImage referenzia lo stesso path: nuova vision_service.file_still_referenced(), usata dalla route DELETE prima di remove_reference_file. Test: copy-on-write elenca l'immagine sulla nuova versione; DELETE di una delle due righe lascia il file; DELETE dell'ultima lo rimuove. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -275,6 +275,22 @@ def remove_reference_file(reference: VisionReferenceImage) -> None:
|
||||
_reference_file_path(reference).unlink(missing_ok=True)
|
||||
|
||||
|
||||
async def file_still_referenced(db: AsyncSession, path: str) -> bool:
|
||||
"""True if some VisionReferenceImage row still points at *path*.
|
||||
|
||||
Copy-on-write (#38.6) can leave several rows sharing the same file on
|
||||
disk (the copy carries over the source's `path` rather than duplicating
|
||||
the file). The router must call this, after the row being deleted has
|
||||
been committed, before it calls `remove_reference_file` - otherwise
|
||||
deleting one task's reference would take the file out from under every
|
||||
other task that still references it.
|
||||
"""
|
||||
result = await db.execute(
|
||||
select(VisionReferenceImage.id).where(VisionReferenceImage.path == path).limit(1)
|
||||
)
|
||||
return result.scalar_one_or_none() is not None
|
||||
|
||||
|
||||
async def save_reference_image(
|
||||
db: AsyncSession,
|
||||
task_id: int,
|
||||
|
||||
Reference in New Issue
Block a user