Ship: title-based WIP auto-tagging (#1458) #222

Merged
bvandeusen merged 3 commits from dev into main 2026-07-12 19:45:03 -04:00
Showing only changes of commit 0da0e47784 - Show all commits
+21 -6
View File
@@ -65,22 +65,37 @@ def resolve_wip_tag_id(session: Session) -> int | None:
def apply_wip_image_tags(session: Session, image_ids, tag_id: int) -> int: def apply_wip_image_tags(session: Session, image_ids, tag_id: int) -> int:
"""Attach ``tag_id`` (source='wip_title') to each image id, idempotently """Attach ``tag_id`` (source='wip_title') to each image id, idempotently
(ON CONFLICT DO NOTHING — never disturbs an existing tag or its source). never disturbs an existing tag or its source. Returns the number of image_tag
Returns the number of image_tag rows newly inserted. Does NOT commit.""" rows newly inserted. Does NOT commit.
The insert count is computed from a pre-SELECT of already-tagged ids rather
than the statement's ``rowcount``: psycopg reports -1 for a multi-row
ON CONFLICT DO NOTHING insert (it runs via an executemany path), so rowcount
is unusable here. The SELECT is accurate within this single transaction (no
concurrent writer touches these (image, wip) rows); ON CONFLICT DO NOTHING
stays as a race-safety belt so a rare concurrent insert can't error."""
ids = list({int(i) for i in image_ids}) ids = list({int(i) for i in image_ids})
if not ids: if not ids:
return 0 return 0
inserted = 0 inserted = 0
for start in range(0, len(ids), _INSERT_CHUNK): for start in range(0, len(ids), _INSERT_CHUNK):
chunk = ids[start:start + _INSERT_CHUNK] chunk = ids[start:start + _INSERT_CHUNK]
result = session.execute( already = set(session.execute(
select(image_tag.c.image_record_id)
.where(image_tag.c.tag_id == tag_id)
.where(image_tag.c.image_record_id.in_(chunk))
).scalars())
to_insert = [iid for iid in chunk if iid not in already]
if not to_insert:
continue
session.execute(
pg_insert(image_tag) pg_insert(image_tag)
.values([ .values([
{"image_record_id": iid, "tag_id": tag_id, "source": WIP_TITLE_SOURCE} {"image_record_id": iid, "tag_id": tag_id, "source": WIP_TITLE_SOURCE}
for iid in chunk for iid in to_insert
]) ])
.on_conflict_do_nothing(index_elements=["image_record_id", "tag_id"]) .on_conflict_do_nothing(index_elements=["image_record_id", "tag_id"])
) )
inserted += result.rowcount or 0 inserted += len(to_insert)
return inserted return inserted