diff --git a/app/api/clips.py b/app/api/clips.py index 2b4db99..b261a4a 100644 --- a/app/api/clips.py +++ b/app/api/clips.py @@ -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: if row is None: - row = ClipAffinity(device_id=device_id) - session.add(row) + # Pierwszy zapis dla urzadzenia. Onboarding i zdarzenia z pierwszych klipow + # 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.niche_weights = aff.niches row.creator_weights = aff.creators