Корень отказов Авито: QRATOR отдаёт proof-of-work челлендж, а мы его не проходим ни одним из путей #3045

Open
opened 2026-08-21 16:27:05 +00:00 by lekss361 · 3 comments
Owner

Найдено 2026-08-21 при разборе #3035/#3044. Это, судя по всему, корневая причина, к которой сводятся и 91-96% отказов avito_detail_backfill, и заметная доля банов SERP. Предыдущие гипотезы — контекст, отпечаток, ротация IP — объясняли данные хуже.

Что отдаёт Авито

Хвост ответа на детальную страницу (получен через tradein-browser, camoufox):

document.addEventListener('DOMContentLoaded', function() {
    if (getCookie('pow_solved')) {
        showStatus('Проверка пройдена, перенаправление...');
        setTimeout(function() { window.location = location.href; }, 3000);
        return;
    }
    startPow(1);
});

Это proof-of-work челлендж QRATOR. Страница считает PoW в JavaScript, ставит куку pow_solved и перезагружает саму себя. Только после этого отдаётся настоящий контент.

Сопутствующие наблюдения, все на живом проде:

Путь Что получаем
curl_cffi (detail, avito_detail_backfill_use_curl=True) HTTP 439, server: QRATOR, «Доступ ограничен: проверка безопасности», 7851 байт
curl_cffi на забаненном IP HTTP 429/403, «Доступ ограничен: проблема с IP» — другой ответ, другая причина
tradein-browser (camoufox) 7894 байта страницы челленджа, без data-marker, без item-view, без __initialData__

Почему это объясняет всё

curl_cffi не решит PoW никогда. JS не исполняется — значит pow_solved не появится — значит 439 навсегда. Ни impersonate=chrome146, ни правильный Sec-Fetch-Site, ни ?context=, ни свежий IP этого не изменят. Все правки, которые мы обсуждали до сих пор, лечили симптомы.

Куки __zzatw-* / cfidsw-* ставятся ПОСЛЕ прохождения проверки. Отсюда наблюдение, которое я сначала счёл багом прогрева: warm_up_session рапортует успех, а кук ноль. Это не баг прогрева — это невозможность их получить без исполнения JS.

Браузер челлендж решить может, но мы не ждём. BrowserFetcher.fetch() (browser_fetcher.py:351) принимает origin и cookies, но не умеет дождаться завершения проверки. Страница сама ставит таймер на 3 секунды и перезагружается — а мы к этому моменту уже забрали HTML и ушли.

Про PoW в коде нет ни слова. grep -rn "pow_solved\|startPow" tradein-mvp/ — ноль совпадений.

И это же бьёт по SERP. Доля отказов avito_city_sweep — 37,5%, avito_full_load — 83%. Когда челлендж прилетает на выдачу, браузер точно так же возвращает заглушку, и прогон пишется баном. То есть починка коснётся не только карточек.

Что делать

Шаг 1 — проверить гипотезу, до всякой разработки. Взять camoufox и после goto дождаться прохождения проверки: перезагрузки, появления куки pow_solved или карточного селектора. Если после ожидания приходит настоящая карточка — гипотеза подтверждена и дальше это инженерная задача. Если нет (PoW требует чего-то, чего camoufox не даёт) — надо знать это до того, как переписывать фетчер.

Шаг 2 — научить tradein-browser ждать челлендж. Детектировать страницу проверки по startPow / заголовку «Доступ ограничен: проверка безопасности», дождаться редиректа, вернуть контент после него. Разумный таймаут и явная ошибка, если проверка не прошла, — вместо тихой отдачи заглушки, как сейчас.

Шаг 3 — увести detail Авито с curl на браузер. Флаг avito_detail_backfill_use_curl (config.py:1007). Только после шага 2, иначе браузер вернёт ту же заглушку.

Мотив, по которому detail когда-то посадили на curl, устарел. В комментарии config.py:999-1003: «SERP и detail_backfill делят один прокси-аккаунт auv… Backconnect (mproxy, авто-ротация)». Аккаунт mproxy закрыт (см. config.py:823), провайдер теперь ASOCKS, оба пути идут через один SCRAPER_PROXY_URL — развязки аккаунтов больше нет, а цена curl-пути выросла до полной неработоспособности.

Шаг 4 — учесть нагрузку. Браузерный фетч тяжелее, а PoW добавит секунды на страницу. avito_detail_backfill ходит батчами — надо замерить, во что это выльется, и не упереться в лимиты ASOCKS. Здесь же пригодится сокращение объёма из #3039/#3041/#3042.

Что это меняет в других задачах

  • #3035 (потеря ?context=) — гипотеза не опровергнута, но приоритет в самый низ: пока запрос не проходит проверку, контекст не имеет значения.
  • #3044 (439 не обработан, 429 конфликтует с баном) — остаётся верным и нужным: коды надо различать. Но теперь ясно, что 439 — это челлендж, а не бан, и правильная реакция на него не ротация IP, а прохождение проверки.
  • #3038 (проверка антибот-кук после прогрева) — становится ещё полезнее: отсутствие кук теперь имеет точную интерпретацию «проверка не пройдена».

Оговорка

Шаг 1 не выполнен — гипотеза, что camoufox досчитает PoW и отдаст карточку, выглядит правдоподобно, но не проверена. Всё остальное в этом issue — наблюдения на живом проде.

Refs #3035, #3044, #3038

Найдено 2026-08-21 при разборе #3035/#3044. Это, судя по всему, **корневая причина**, к которой сводятся и 91-96% отказов `avito_detail_backfill`, и заметная доля банов SERP. Предыдущие гипотезы — контекст, отпечаток, ротация IP — объясняли данные хуже. ## Что отдаёт Авито Хвост ответа на детальную страницу (получен через `tradein-browser`, camoufox): ```js document.addEventListener('DOMContentLoaded', function() { if (getCookie('pow_solved')) { showStatus('Проверка пройдена, перенаправление...'); setTimeout(function() { window.location = location.href; }, 3000); return; } startPow(1); }); ``` Это **proof-of-work челлендж QRATOR**. Страница считает PoW в JavaScript, ставит куку `pow_solved` и перезагружает саму себя. Только после этого отдаётся настоящий контент. Сопутствующие наблюдения, все на живом проде: | Путь | Что получаем | |---|---| | `curl_cffi` (detail, `avito_detail_backfill_use_curl=True`) | `HTTP 439`, `server: QRATOR`, «Доступ ограничен: **проверка безопасности**», 7851 байт | | `curl_cffi` на забаненном IP | `HTTP 429`/`403`, «Доступ ограничен: **проблема с IP**» — другой ответ, другая причина | | `tradein-browser` (camoufox) | 7894 байта **страницы челленджа**, без `data-marker`, без `item-view`, без `__initialData__` | ## Почему это объясняет всё **curl_cffi не решит PoW никогда.** JS не исполняется — значит `pow_solved` не появится — значит 439 навсегда. Ни `impersonate=chrome146`, ни правильный `Sec-Fetch-Site`, ни `?context=`, ни свежий IP этого не изменят. Все правки, которые мы обсуждали до сих пор, лечили симптомы. **Куки `__zzatw-*` / `cfidsw-*` ставятся ПОСЛЕ прохождения проверки.** Отсюда наблюдение, которое я сначала счёл багом прогрева: `warm_up_session` рапортует успех, а кук ноль. Это не баг прогрева — это невозможность их получить без исполнения JS. **Браузер челлендж решить может, но мы не ждём.** `BrowserFetcher.fetch()` (`browser_fetcher.py:351`) принимает `origin` и `cookies`, но не умеет дождаться завершения проверки. Страница сама ставит таймер на 3 секунды и перезагружается — а мы к этому моменту уже забрали HTML и ушли. **Про PoW в коде нет ни слова.** `grep -rn "pow_solved\|startPow" tradein-mvp/` — ноль совпадений. **И это же бьёт по SERP.** Доля отказов `avito_city_sweep` — 37,5%, `avito_full_load` — 83%. Когда челлендж прилетает на выдачу, браузер точно так же возвращает заглушку, и прогон пишется баном. То есть починка коснётся не только карточек. ## Что делать **Шаг 1 — проверить гипотезу, до всякой разработки.** Взять camoufox и после `goto` дождаться прохождения проверки: перезагрузки, появления куки `pow_solved` или карточного селектора. Если после ожидания приходит настоящая карточка — гипотеза подтверждена и дальше это инженерная задача. Если нет (PoW требует чего-то, чего camoufox не даёт) — надо знать это до того, как переписывать фетчер. **Шаг 2 — научить `tradein-browser` ждать челлендж.** Детектировать страницу проверки по `startPow` / заголовку «Доступ ограничен: проверка безопасности», дождаться редиректа, вернуть контент после него. Разумный таймаут и явная ошибка, если проверка не прошла, — вместо тихой отдачи заглушки, как сейчас. **Шаг 3 — увести detail Авито с curl на браузер.** Флаг `avito_detail_backfill_use_curl` (`config.py:1007`). **Только после шага 2**, иначе браузер вернёт ту же заглушку. Мотив, по которому detail когда-то посадили на curl, устарел. В комментарии `config.py:999-1003`: «SERP и detail_backfill делят один прокси-аккаунт **auv**… Backconnect (**mproxy**, авто-ротация)». Аккаунт mproxy закрыт (см. `config.py:823`), провайдер теперь ASOCKS, оба пути идут через один `SCRAPER_PROXY_URL` — развязки аккаунтов больше нет, а цена curl-пути выросла до полной неработоспособности. **Шаг 4 — учесть нагрузку.** Браузерный фетч тяжелее, а PoW добавит секунды на страницу. `avito_detail_backfill` ходит батчами — надо замерить, во что это выльется, и не упереться в лимиты ASOCKS. Здесь же пригодится сокращение объёма из #3039/#3041/#3042. ## Что это меняет в других задачах - **#3035** (потеря `?context=`) — гипотеза не опровергнута, но приоритет в самый низ: пока запрос не проходит проверку, контекст не имеет значения. - **#3044** (439 не обработан, 429 конфликтует с баном) — остаётся верным и нужным: коды надо различать. Но теперь ясно, что `439` — это **челлендж**, а не бан, и правильная реакция на него не ротация IP, а прохождение проверки. - **#3038** (проверка антибот-кук после прогрева) — становится ещё полезнее: отсутствие кук теперь имеет точную интерпретацию «проверка не пройдена». ## Оговорка Шаг 1 **не выполнен** — гипотеза, что camoufox досчитает PoW и отдаст карточку, выглядит правдоподобно, но не проверена. Всё остальное в этом issue — наблюдения на живом проде. Refs #3035, #3044, #3038
lekss361 added the
bug
priority/p1
scope/backend
scrapers
tradein
labels 2026-08-21 16:27:15 +00:00
Author
Owner

Шаг 1 выполнен: гипотеза подтверждена, и уточнена

Две пробы на живом проде, обе через tradein-browser (camoufox).

Проба A — холодный goto прямо на карточку

# Размер Что пришло
1 881 655 настоящая карточка — «1-к. квартира, 41 м², 22/27 эт.»
2 881 851 настоящая карточка
3 30 644 «Доступ ограничен: проблема с IP»
4 7 894 PoW-челлендж

Браузер отдаёт полноценную карточку — 881 КБ, заголовок, data-marker на месте. Тот же URL через curl_cffi на том же адресе давал 439 без исключений. Шаг 1 закрыт: переключение detail на браузер обосновано.

Проба B — органическая навигация (origin = выдача вторички)

Шесть разных карточек, пауза 8 с, f.fetch(url, origin=SERP):

# Результат
1, 2, 3, 5 PoW-челлендж, «проверка безопасности»
4 карточка, 610 880 байт
6 карточка, 851 866 байт — «2-к. квартира, 38 м², 2/9 эт.»

2 из 6.

Главный вывод: изменился тип отказа

В пробе A потолок упирался в бан адреса. В пробе B, с органической навигацией, ни одного бана — все четыре неудачи это челлендж, который мы не дождались.

То есть площадка нас не блокирует. Мы уходим со страницы раньше, чем она досчитала проверку.

Это классическая картина фиксированного таймаута на задаче переменной длительности. server.py:949-951:

await page.goto(url, timeout=BROWSER_NAV_TIMEOUT_MS, wait_until="domcontentloaded")
await page.wait_for_timeout(BROWSER_WAIT_MS)   # 6000 для avito
html = await page.content()

Шести секунд хватает на гидратацию обычной страницы (ради чего константу и подняли с 2500 — см. комментарий server.py:111), но не на цепочку «PoW-вычисление → таймер 3 с → перезагрузка → гидратация новой страницы». Иногда укладывается — два раза из шести.

Что это меняет в плане

Шаг 2 остаётся, но становится точечным и предсказуемым. Не «переписать фетчер», а: после goto проверить, не челлендж ли это (startPow в разметке / заголовок «проверка безопасности»), и если да — дождаться перезагрузки вместо фиксированной паузы. Явная ошибка по таймауту вместо тихой отдачи заглушки, как сейчас.

Ожидаемый эффект — не «33% вместо 8%», а близко к сотне: блокировки нет, есть недождавшийся клиент.

Шаг 3 (флаг avito_detail_backfill_use_curl → False) — после шага 2, иначе браузер продолжит отдавать заглушку в тех же двух третях случаев.

Пессимизм про «две карточки на адрес» снимается. Он был артефактом холодного goto в пробе A: запрос ниоткуда — сам по себе аномалия, и адрес за неё горит. С органической навигацией баны исчезли на той же серии.

И это поднимает обратно #3035. origin и сохранённый ?context= — две стороны одного: сделать так, чтобы карточка выглядела пришедшей с выдачи. Отдельной задачей контекст больше не выглядит, он часть той же работы.

Оговорки

  • Выборки маленькие: 4 и 6 запросов. Направление видно чётко (тип отказа сменился), точные доли — нет.
  • Узел asocks-mobile-2 я сегодня уже нагружал пробами, так что бан в пробе A мог быть накопленным.
  • Успех №4 пришёл без <title>, 610 КБ — вероятно, снимок до конца гидратации. То есть даже среди успехов есть недождавшиеся; ожидание нужно и им.

Refs #3035, #3044

## Шаг 1 выполнен: гипотеза подтверждена, и уточнена Две пробы на живом проде, обе через `tradein-browser` (camoufox). ### Проба A — холодный `goto` прямо на карточку | # | Размер | Что пришло | |---|---|---| | 1 | **881 655** | **настоящая карточка** — «1-к. квартира, 41 м², 22/27 эт.» | | 2 | **881 851** | **настоящая карточка** | | 3 | 30 644 | «Доступ ограничен: **проблема с IP**» | | 4 | 7 894 | PoW-челлендж | Браузер **отдаёт полноценную карточку** — 881 КБ, заголовок, `data-marker` на месте. Тот же URL через `curl_cffi` на том же адресе давал `439` без исключений. Шаг 1 закрыт: переключение detail на браузер обосновано. ### Проба B — органическая навигация (`origin` = выдача вторички) Шесть **разных** карточек, пауза 8 с, `f.fetch(url, origin=SERP)`: | # | Результат | |---|---| | 1, 2, 3, 5 | PoW-челлендж, «проверка безопасности» | | 4 | карточка, 610 880 байт | | 6 | карточка, 851 866 байт — «2-к. квартира, 38 м², 2/9 эт.» | **2 из 6.** ### Главный вывод: изменился тип отказа В пробе A потолок упирался в **бан адреса**. В пробе B, с органической навигацией, **ни одного бана** — все четыре неудачи это **челлендж**, который мы не дождались. То есть площадка нас не блокирует. Мы уходим со страницы раньше, чем она досчитала проверку. Это классическая картина фиксированного таймаута на задаче переменной длительности. `server.py:949-951`: ```python await page.goto(url, timeout=BROWSER_NAV_TIMEOUT_MS, wait_until="domcontentloaded") await page.wait_for_timeout(BROWSER_WAIT_MS) # 6000 для avito html = await page.content() ``` Шести секунд хватает на гидратацию обычной страницы (ради чего константу и подняли с 2500 — см. комментарий `server.py:111`), но не на цепочку «PoW-вычисление → таймер 3 с → перезагрузка → гидратация новой страницы». Иногда укладывается — два раза из шести. ### Что это меняет в плане **Шаг 2 остаётся, но становится точечным и предсказуемым.** Не «переписать фетчер», а: после `goto` проверить, не челлендж ли это (`startPow` в разметке / заголовок «проверка безопасности»), и если да — дождаться перезагрузки вместо фиксированной паузы. Явная ошибка по таймауту вместо тихой отдачи заглушки, как сейчас. Ожидаемый эффект — не «33% вместо 8%», а близко к сотне: блокировки нет, есть недождавшийся клиент. **Шаг 3 (флаг `avito_detail_backfill_use_curl` → False) — после шага 2**, иначе браузер продолжит отдавать заглушку в тех же двух третях случаев. **Пессимизм про «две карточки на адрес» снимается.** Он был артефактом холодного `goto` в пробе A: запрос ниоткуда — сам по себе аномалия, и адрес за неё горит. С органической навигацией баны исчезли на той же серии. **И это поднимает обратно #3035.** `origin` и сохранённый `?context=` — две стороны одного: сделать так, чтобы карточка выглядела пришедшей с выдачи. Отдельной задачей контекст больше не выглядит, он часть той же работы. ### Оговорки - Выборки маленькие: 4 и 6 запросов. Направление видно чётко (тип отказа сменился), точные доли — нет. - Узел `asocks-mobile-2` я сегодня уже нагружал пробами, так что бан в пробе A мог быть накопленным. - Успех №4 пришёл без `<title>`, 610 КБ — вероятно, снимок до конца гидратации. То есть даже среди успехов есть недождавшиеся; ожидание нужно и им. Refs #3035, #3044
Collaborator

Замер 28.08.2026: авторизованная сессия проходит там, где анонимная получает 439/403.

Проверено вживую, одна и та же карточка 8273772563, один и тот же адрес, разница только в сессии:

аноним залогиненный сеанс
ответ 403 / 439 200
размер заглушка 6 756 б 1 064 467 б
цена в разметке 8 650 000 ₽
параметров 19
антибот-куки нет __zzatw-avito, cfidsw-avito, sx, f

Затем пять карточек подряд из той же сессии, пауза 1,5 с:

200  779 802 б  481 мс
200  759 535 б  316 мс
200  789 714 б  352 мс
200  806 944 б  482 мс
200  740 594 б  482 мс

Пять из пяти, ноль блоков. Для сравнения, прод в тот же день: прогон 5190 — пять попыток за 72 секунды, то есть с бОльшими паузами, и пять блоков подряд, enriched=0.

Отсюда прямой вывод: дело не в темпе и не в адресе. Анонимный запрос к карточке отбивается независимо от IP — я получил 439 и со своей домашней машины, и после прогрева сессии на выдаче. Владелец получил «проблема с IP» на своём адресе, при том что выдача у него открывалась.

Что делает сессию проходной

  • антибот-куки __zzatw-avito / cfidsw-avito — ровно те, отсутствие которых код репортит как AvitoWarmupCookiesMissingError;
  • cookie авторизации — HttpOnly, в document.cookie не видна (там только buyer_location_id, buyer_from_page). Переносить сессию в скраппер нужно на уровне CDP (Network.getAllCookies), а не через JS;
  • ?context= из выдачи — карточки открывались с ним (ср. #3035, где бэкфилл его отрезает).

Что это значит для планов

Мой предварительный вывод был «аккаунты не помогут, рубит по IP до проверки авторизации». Замер его опроверг — привожу как есть.

Отдельно объяснилась деградация: 22.08 коммит b61123d7 перевёл прод на браузерный режим, а прогрев сессии (яндексовый referer → поиск Авито → антибот-куки) реализован только для curl-путиwarm_up_session принимает AsyncSession. Браузерный путь ходит на карточки холодным, и обогащение затухало четыре дня: 161 → 161 → 116 → 23 → 1 → 2.

**Замер 28.08.2026: авторизованная сессия проходит там, где анонимная получает 439/403.** Проверено вживую, одна и та же карточка `8273772563`, один и тот же адрес, разница только в сессии: | | аноним | залогиненный сеанс | |---|---|---| | ответ | 403 / 439 | **200** | | размер | заглушка 6 756 б | **1 064 467 б** | | цена в разметке | — | 8 650 000 ₽ | | параметров | — | 19 | | антибот-куки | нет | **`__zzatw-avito`, `cfidsw-avito`, `sx`, `f`** | Затем пять карточек подряд из той же сессии, пауза 1,5 с: ``` 200 779 802 б 481 мс 200 759 535 б 316 мс 200 789 714 б 352 мс 200 806 944 б 482 мс 200 740 594 б 482 мс ``` **Пять из пяти, ноль блоков.** Для сравнения, прод в тот же день: прогон 5190 — пять попыток за 72 секунды, то есть с бОльшими паузами, и **пять блоков подряд, `enriched=0`**. Отсюда прямой вывод: **дело не в темпе и не в адресе**. Анонимный запрос к карточке отбивается независимо от IP — я получил 439 и со своей домашней машины, и после прогрева сессии на выдаче. Владелец получил «проблема с IP» на своём адресе, при том что выдача у него открывалась. ## Что делает сессию проходной - антибот-куки `__zzatw-avito` / `cfidsw-avito` — ровно те, отсутствие которых код репортит как `AvitoWarmupCookiesMissingError`; - cookie авторизации — **`HttpOnly`**, в `document.cookie` не видна (там только `buyer_location_id`, `buyer_from_page`). Переносить сессию в скраппер нужно на уровне CDP (`Network.getAllCookies`), а не через JS; - `?context=` из выдачи — карточки открывались с ним (ср. #3035, где бэкфилл его отрезает). ## Что это значит для планов Мой предварительный вывод был «аккаунты не помогут, рубит по IP до проверки авторизации». **Замер его опроверг** — привожу как есть. Отдельно объяснилась деградация: 22.08 коммит `b61123d7` перевёл прод на браузерный режим, а прогрев сессии (яндексовый referer → поиск Авито → антибот-куки) реализован **только для curl-пути** — `warm_up_session` принимает `AsyncSession`. Браузерный путь ходит на карточки холодным, и обогащение затухало четыре дня: 161 → 161 → 116 → 23 → 1 → 2.
Collaborator

Уточнение к моему же выводу: «дело не в адресе» — сказано слишком сильно.

Прогон 5200, стартовал 16:47 уже на обновлённых прокси, через 8 минут:

attempted=25  enriched=16  blocked=9   status=running

Против семи предыдущих прогонов, все banned, enriched 0-2:

прогон время статус enriched/attempted
5200 28.08 16:47 running 16/25
5190 28.08 13:47 banned 0/5
5182 28.08 10:47 banned 0/5
5169 28.08 07:46 banned 2/11
5152 28.08 04:46 banned 0/5
5140 28.08 01:46 banned 0/5
5129 27.08 22:46 banned 0/5

Свежий адрес возвращает анонимный сбор — 64% успеха вместо нуля. Значит адрес влияет, и моя формулировка это смазала.

Что остаётся верным без изменений: в один и тот же момент, на выгоревшем адресе, авторизованная сессия дала 5/5, анонимная — 0/5. И 36% блоков в 5200 — это всё ещё блоки на свежем адресе, а история показывает, как эта доля растёт (161 → 161 → 116 → 23 → 1 → 2 по дням).

Аккуратная формулировка: адрес задаёт стартовый запас, сессия — насколько быстро он тратится. Обновление IP — расходник (владелец меняет их вручную), сессия — то, что переживает прогоны. Обе части нужны; строить надо ту, что не требует ручного вмешательства раз в несколько дней.

**Уточнение к моему же выводу: «дело не в адресе» — сказано слишком сильно.** Прогон **5200**, стартовал 16:47 уже на обновлённых прокси, через 8 минут: ``` attempted=25 enriched=16 blocked=9 status=running ``` Против семи предыдущих прогонов, все `banned`, `enriched` 0-2: | прогон | время | статус | enriched/attempted | |---|---|---|---| | **5200** | 28.08 16:47 | **running** | **16/25** | | 5190 | 28.08 13:47 | banned | 0/5 | | 5182 | 28.08 10:47 | banned | 0/5 | | 5169 | 28.08 07:46 | banned | 2/11 | | 5152 | 28.08 04:46 | banned | 0/5 | | 5140 | 28.08 01:46 | banned | 0/5 | | 5129 | 27.08 22:46 | banned | 0/5 | Свежий адрес **возвращает анонимный сбор** — 64% успеха вместо нуля. Значит адрес влияет, и моя формулировка это смазала. Что остаётся верным без изменений: в один и тот же момент, на выгоревшем адресе, авторизованная сессия дала 5/5, анонимная — 0/5. И 36% блоков в 5200 — это всё ещё блоки на свежем адресе, а история показывает, как эта доля растёт (161 → 161 → 116 → 23 → 1 → 2 по дням). **Аккуратная формулировка:** адрес задаёт стартовый запас, сессия — насколько быстро он тратится. Обновление IP — расходник (владелец меняет их вручную), сессия — то, что переживает прогоны. Обе части нужны; строить надо ту, что не требует ручного вмешательства раз в несколько дней.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
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#3045
No description provided.