fix(importer): ImageProvenance (image_record_id, post_id) race-safe via savepoint + alembic 0021 UNIQUE — closes the SELECT-then-INSERT window that planted duplicates and broke .scalar_one_or_none() on every later deep-scan rederive (MultipleResultsFound). Migration dedupes existing rows (min(id) per pair); model gains __table_args__; gallery-filter test that seeded duplicates dropped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
"""ImageProvenance — links an ImageRecord to a Post.
|
||||
|
||||
Many-to-one (one image, many provenance rows) enables the enrich-on-duplicate
|
||||
rule (spec §3): when a downloaded image is a pHash dupe of an existing
|
||||
record, we append a new provenance row to the existing record rather than
|
||||
dropping the metadata.
|
||||
One image can have many provenance rows — different posts each contribute
|
||||
metadata (enrich-on-duplicate rule, spec §3: a downloaded image that is a
|
||||
pHash dupe of an existing record gets a NEW provenance row for the new post
|
||||
appended, rather than the metadata being dropped). But the (image, post)
|
||||
pair is unique — alembic 0021 enforces uq_image_provenance_image_post
|
||||
after operator-flagged 2026-05-26 saw _apply_sidecar's existence-check +
|
||||
INSERT race plant duplicates that then broke .scalar_one_or_none() on
|
||||
every later deep-scan rederive (MultipleResultsFound).
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import JSON, DateTime, ForeignKey, Integer, func
|
||||
from sqlalchemy import JSON, DateTime, ForeignKey, Integer, UniqueConstraint, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from .base import Base
|
||||
@@ -16,6 +20,12 @@ from .base import Base
|
||||
|
||||
class ImageProvenance(Base):
|
||||
__tablename__ = "image_provenance"
|
||||
__table_args__ = (
|
||||
UniqueConstraint(
|
||||
"image_record_id", "post_id",
|
||||
name="uq_image_provenance_image_post",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
image_record_id: Mapped[int] = mapped_column(
|
||||
|
||||
Reference in New Issue
Block a user