perf(tags): protective-alias uses tag kind, drops the image_record full scan
_create_protective_aliases scanned every image_record's tagger_predictions JSON (unindexed full scan, ~59k rows) to find the categories a merged-away tag's name was predicted under. That scan ran inside the merge transaction AFTER it had locked series_page — on a large library it held that lock for minutes and is what blocked migration 0040 (and starved the standardization task into its 40-min timeout). The scan was redundant: the tagger's tag_to_category map is one-to-one (a name has exactly one category) and a tag's kind is set from that category when created, so kind already IS the tagger's category for the name. The scan only ever rediscovered the kind. Build the single protective alias from src_kind directly — no scan, no lock-holding slow step in the merge. Rewrote test_alias_per_observed_prediction_category (which encoded the can't-actually-happen one-name-two-categories case) → test_protective_alias_uses_tag_kind. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -320,7 +320,12 @@ async def test_no_alias_when_purely_manual(db):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_alias_per_observed_prediction_category(db):
|
||||
async def test_protective_alias_uses_tag_kind(db):
|
||||
# The protective alias category is the tag's KIND — the tagger maps each name
|
||||
# to exactly one category and a tag's kind is set from it, so kind already IS
|
||||
# the tagger's category. The merge no longer scans image_record's predictions
|
||||
# to rediscover it. Even with a (contrived) differing prediction category
|
||||
# present, the merge writes a single (name, kind) alias.
|
||||
from backend.app.models import ImageRecord
|
||||
from backend.app.models.tag_alias import TagAlias
|
||||
|
||||
@@ -332,11 +337,6 @@ async def test_alias_per_observed_prediction_category(db):
|
||||
await svc.add_to_image(img, a.id, source="ml_auto")
|
||||
r1 = await db.get(ImageRecord, img)
|
||||
r1.tagger_predictions = {
|
||||
"predname": {"category": "general", "confidence": 0.9}
|
||||
}
|
||||
i2 = await _img(db)
|
||||
r2 = await db.get(ImageRecord, i2)
|
||||
r2.tagger_predictions = {
|
||||
"predname": {"category": "copyright", "confidence": 0.8}
|
||||
}
|
||||
await db.flush()
|
||||
@@ -353,7 +353,6 @@ async def test_alias_per_observed_prediction_category(db):
|
||||
).all()
|
||||
assert {(r.alias_string, r.alias_category) for r in rows} == {
|
||||
("predname", "general"),
|
||||
("predname", "copyright"),
|
||||
}
|
||||
assert all(r.canonical_tag_id == b.id for r in rows)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user