fix(ptica): ключ синглтон-лока kn-свипа зависит от множества, а не от порядка (#2464) #2970

Merged
bot-backend merged 1 commit from fix/2464-lock-key-order into main 2026-08-20 10:34:31 +00:00
Collaborator

Пункт эпика #2464: scrape_kn.py:42.

Дефект

devs_key = ",".join(developers) if developers else "*"

Список джойнится как пришёл, а приходит он прямо из тела запроса (developers в admin_scrape, порядок произвольный).

Один и тот же набор в другом порядке даёт другой ключ:

scrape:kn:lock:66:6208_0,1234_5,9999_1
scrape:kn:lock:66:9999_1,6208_0,1234_5

Синглтон молча перестаёт быть синглтоном: два свипа идут параллельно по одним и тем же разработчикам.

Второе следствие того же корня

force_release_lock строит ключ этой же функцией. Оператор, снимающий залипший лок и перечисливший разработчиков в ином порядке, молча не снимает ничего.

Правка

sorted(set(...)) — закрывает и порядок, и повторы ('A','A' ≡ 'A').

Про переход

Формат ключа меняется, поэтому лок, удерживаемый прямо сейчас под старым ключом, осиротеет и истечёт по TTL. Практического риска нет: kn-свип не отрабатывает с 28.06 — DOM.РФ отдаёт страницу блокировки (#2443).

Тест

Сравнивает значения ключей, поэтому красное на origin/main — про разошедшиеся ключи, а не про отсутствующую функцию:

один набор в двух порядках → два разных ключа  → падает
повтор в списке меняет ключ                    → падает
разные наборы остаются разными → контроль, зелёный с обеих сторон
регион остаётся в ключе        → контроль, зелёный с обеих сторон
None/[] по-прежнему дают '*'   → контроль, зелёный с обеих сторон

Первый контроль не для симметрии: ловит «починку» через огрубление ключа (отбросить developers вовсе) — тогда свипы по разным разработчикам блокировали бы друг друга.

Прогоны

-k "scrape_kn or lock"   114 passed   rc=0
Пункт эпика #2464: `scrape_kn.py:42`. ## Дефект ```python devs_key = ",".join(developers) if developers else "*" ``` Список джойнится **как пришёл**, а приходит он прямо из тела запроса (`developers` в `admin_scrape`, порядок произвольный). Один и тот же набор в другом порядке даёт **другой ключ**: ``` scrape:kn:lock:66:6208_0,1234_5,9999_1 scrape:kn:lock:66:9999_1,6208_0,1234_5 ``` Синглтон молча перестаёт быть синглтоном: два свипа идут параллельно по одним и тем же разработчикам. ## Второе следствие того же корня `force_release_lock` строит ключ **этой же функцией**. Оператор, снимающий залипший лок и перечисливший разработчиков в ином порядке, молча не снимает ничего. ## Правка `sorted(set(...))` — закрывает и порядок, и повторы (`'A','A' ≡ 'A'`). ## Про переход Формат ключа меняется, поэтому лок, удерживаемый **прямо сейчас** под старым ключом, осиротеет и истечёт по TTL. Практического риска нет: kn-свип не отрабатывает с 28.06 — DOM.РФ отдаёт страницу блокировки (#2443). ## Тест Сравнивает **значения** ключей, поэтому красное на `origin/main` — про разошедшиеся ключи, а не про отсутствующую функцию: ``` один набор в двух порядках → два разных ключа → падает повтор в списке меняет ключ → падает разные наборы остаются разными → контроль, зелёный с обеих сторон регион остаётся в ключе → контроль, зелёный с обеих сторон None/[] по-прежнему дают '*' → контроль, зелёный с обеих сторон ``` Первый контроль не для симметрии: ловит «починку» через огрубление ключа (отбросить `developers` вовсе) — тогда свипы по разным разработчикам блокировали бы друг друга. ## Прогоны ``` -k "scrape_kn or lock" 114 passed rc=0 ```
bot-backend added 1 commit 2026-08-20 10:15:33 +00:00
fix(ptica): ключ синглтон-лока kn-свипа зависит от множества, а не от порядка (#2464)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 9s
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m22s
CI / backend-tests (pull_request) Successful in 17m12s
fd2fc945a7
devs_key = ",".join(developers) — список джойнился как пришёл, а приходит он прямо
из тела запроса (`developers` в admin_scrape, порядок произвольный). Один и тот же
набор в другом порядке давал ДРУГОЙ ключ: синглтон молча переставал быть
синглтоном, два свипа шли параллельно по одним и тем же разработчикам.

Второе следствие того же корня: force_release_lock строит ключ этой же функцией.
Оператор, снимающий залипший лок и перечисливший разработчиков в ином порядке,
молча не снимал ничего.

sorted(set(...)) закрывает оба случая: порядок и повторы ('A','A' ≡ 'A').

Про переход: формат ключа меняется, поэтому лок, удерживаемый ПРЯМО СЕЙЧАС под
старым ключом, осиротеет и истечёт по TTL. Практического риска нет — kn-свип
не отрабатывает с 28.06 (DOM.РФ отдаёт страницу блокировки, см. #2443).

Тесты сравнивают ЗНАЧЕНИЯ ключей, поэтому красное на origin/main — про разошедшиеся
ключи, а не про отсутствующую функцию:

  один набор в двух порядках → два разных ключа  → падает
  повтор в списке меняет ключ                    → падает
  разные наборы остаются разными    — контроль, зелёный с обеих сторон
  регион остаётся в ключе           — контроль, зелёный с обеих сторон
  None/[] по-прежнему дают '*'      — контроль, зелёный с обеих сторон

Первый контроль не для симметрии: ловит «починку» через огрубление ключа
(отбросить developers вовсе) — тогда свипы по разным разработчикам блокировали бы
друг друга.

Прогоны: -k "scrape_kn or lock" — 114 passed rc=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bot-backend merged commit a899cb9b1f into main 2026-08-20 10:34:31 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2970
No description provided.