fix(clips): wyscig przy pierwszym zapisie afinicznosci urzadzenia

Onboarding Edge i zdarzenia z pierwszych klipow przychodza naraz, oba
widzialy brak wiersza clip_affinity i oba robily INSERT, drugi konczyl sie
UniqueViolation i bledem 500 (GOON-7X). Pusty wiersz przez ON CONFLICT DO
NOTHING, potem odczyt z blokada i dodanie naszych przyrostow do tego, co
zapisalo rownolegle zadanie. Test z dwoma watkami: bez bledow, obie wagi.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
goon-foss 2026-10-06 15:52:54 +02:00
parent 5001d79bbc
commit 7e48cdee06

View file

@ -214,8 +214,20 @@ def _load_affinity(session: Session, device_id: str) -> tuple[ClipAffinity | Non
def _save_affinity(session: Session, device_id: str, row: ClipAffinity | None, aff: cf.Affinity, events: int) -> None: def _save_affinity(session: Session, device_id: str, row: ClipAffinity | None, aff: cf.Affinity, events: int) -> None:
if row is None: if row is None:
row = ClipAffinity(device_id=device_id) # Pierwszy zapis dla urzadzenia. Onboarding i zdarzenia z pierwszych klipow
session.add(row) # przychodza naraz, oba widzialy brak wiersza i oba robily INSERT, drugi konczyl
# sie UniqueViolation i bledem 500 (GOON-7X). Wstawiamy pusty wiersz z ON CONFLICT
# i bierzemy go z blokada. Nasze wagi liczylismy od zera, wiec to same przyrosty:
# dodajemy je do tego, co zdazylo zapisac rownolegle zadanie.
session.execute(
pg_insert(ClipAffinity)
.values(device_id=device_id, tag_weights={}, niche_weights={}, creator_weights={}, events_seen=0)
.on_conflict_do_nothing(index_elements=["device_id"])
)
row = session.get(ClipAffinity, device_id, with_for_update=True, populate_existing=True)
for mine, theirs in ((aff.tags, row.tag_weights), (aff.niches, row.niche_weights), (aff.creators, row.creator_weights)):
for k, v in (theirs or {}).items():
mine[k] = round(mine.get(k, 0.0) + v, 3)
row.tag_weights = aff.tags row.tag_weights = aff.tags
row.niche_weights = aff.niches row.niche_weights = aff.niches
row.creator_weights = aff.creators row.creator_weights = aff.creators