Files
av-parser/docs/proxies.md
T
Leonid Pershin 0aa3a7cf11 Implement media rule editor and enhance gallery functionality
- Introduced a rule editor in the gallery for users to define actions when a media item is found again, allowing for better management of media rules.
- Updated `GalleryViewModel` to handle rule actions, including saving, editing, and removing rules, with appropriate UI bindings.
- Enhanced UI components in `GalleryView.axaml` to support rule editing, including action selection and source management.
- Added localization strings for new rule-related features in both English and Russian.
- Improved unit tests to cover new rule management functionalities, ensuring robust behavior during rule creation and editing.

These changes significantly enhance the user experience by providing a more interactive and flexible way to manage media items in the gallery.
2026-08-15 16:03:02 +03:00

9.3 KiB
Raw Blame History

Прокси-пул

Читать перед правкой Core/Proxies/** и Infrastructure/Proxies/**.

Добавить источник

  1. Реализовать IProxySource (или IMutableProxySource, если список редактируемый).
  2. Зарегистрировать в AddAvParserProxies(). Порядок регистрации = порядок слияния; свой список идёт последним, чтобы пользовательский адрес перебивал фидовый.

Инварианты

  • ProxyPool переиспользует существующие ProxyEntry по Endpoint.Key — иначе перезагрузка списка стирала бы статистику, а публичные фиды переиздаются каждые несколько минут.
  • Проба обязана ходить по https. Обычный HTTP через прокси — это форвард GET с абсолютным URI, а https — CONNECT-туннель, и свободные прокси сплошь и рядом умеют первое и отказывают во втором («The proxy tunnel request to proxy … failed with status code 400»). Все собираемые адреса идут по https, поэтому прокси без CONNECT мертва для нас, и проверять надо ровно то, чем пользуемся. Раньше умолчание было http с обоснованием «не отбраковывать тех, кто просто не умеет CONNECT» — это и наполняло пул живыми на бумаге. Старое значение в settings.json подменяется на https в AppSettings.ToProxyOptions(); введённое пользователем не трогается.
  • Выдаются только подтверждённо живые, пока такие есть. Сортировки «живые вперёд» не хватало: её видит только липкая стратегия, берущая голову списка, а round-robin и взвешенный выбор тянут из всего набора — то есть из пары тысяч непроверенных адресов, и почти каждый запрос платил полный connect-таймаут, чтобы это выяснить. Теперь «живых N» на странице и то, куда реально ходит сбор, — одно и то же число.
  • AcquireAsync(excludedCountries) — для правила «попробовать из другой страны». Записи, у которых фид не назвал страну, остаются в игре: неизвестная страна — не совпадение, и отбрасывать их значит сужать пул из-за пустого поля.
  • Фолбэк на всё доступное, когда живых нет. Непроверенная ≠ мёртвая: на холодном пуле строгий фильтр не выдал бы ничего и сбор просто встал бы, не попробовав. Ответившая на этом пути прокси сама себя переводит в живые.
  • Карантин остаётся отдельным механизмом от Health. Health — «что видели в последний раз»; исключать навсегда всё когда-либо упавшее значит потерять прокси после первой осечки. Уже было багом, ловит A_failing_proxy_is_quarantined_and_comes_back_later.
  • LiveCount считает только Alive и не в карантине. На нём висит гейт сбора, поэтому «доступна» (окно истекло) и «живая» намеренно расходятся: гейт не должен открываться от одного лишь истечения окна.
  • Проба не трогает SuccessCount/FailureCount — они про реальные запросы, а свип по паре тысяч адресов перезаписал бы всё, на чём держится взвешенный выбор. Провал пробы даёт карантин через RecordProbe(..., quarantineOnFailure:).
  • Лиза без вердикта нейтральна: отменённая операция — не вина прокси, иначе каждый Cancel карантинил бы здоровые адреса.
  • Вердикт лизы — про транспорт, а не про ресурс. 404 и 429 — успех прокси; иначе пул карантинил бы рабочие адреса с частотой мёртвых ссылок, а на лимит отвечал бы сменой прокси, то есть обходом лимита.
  • Прогрев обрывается по достижении цели, а не проходит список до конца: WarmUpAsync линкует CTS и гасит остаток на MinimumLiveProxies. Порядок кандидатов — WarmUpOrder(), публичный ровно ради проверки без прогона проб.
  • Остаток дочищает TopUpAsync в фоне. Прогрев по построению оставляет тысячи адресов в Unknown — это читается как «проверка не запускалась», и, что хуже, сбор получает пул из десяти прокси вместо сотен рабочих. Фоновый проход запускает ProxyPoolLoader после прогрева, с четвертью ProbeConcurrency: пользовательский свип — это всплеск, за которым смотрят, а этот идёт минутами и, возможно, параллельно с закачкой.
  • TopUpAsync трогает только Unknown. Перепроверять мёртвых — это и есть свип; перепроверять живых значит посадить в карантин прокси, которой прямо сейчас пользуется прогон.
  • TopUpAsync не делает _strategy.Reset(), в отличие от свипа: сброс уронил бы липкий выбор посреди сбора, причём ради записей, которых в этом выборе и нет. Changed он поднимает раз в ChangeInterval проб — иначе страница молчит несколько минут.
  • Фоновый проход не идёт при ProxyHealthCheck.Lazy: «проверять в момент выдачи» — это ровно просьба не свипать.
  • SaveStateAsync сериализован семафором. Писателей теперь двое (фоновый проход по завершении и выход из приложения), а запись идёт через один и тот же временный файл с переименованием.
  • RestoreState не выставляет Health = Alive — «работала вчера» живёт в WasAliveOnLastRun и влияет только на порядок прогрева. Иначе пул отрапортует живыми тех, с кем не разговаривал: прогрев сочтёт цель достигнутой, а гейт сбора откроется по данным недельной давности. Ловит A_remembered_proxy_is_not_reported_live_until_it_answers_again.
  • RestoreState не восстанавливает карантин: окно — стенные часы, между запусками могли пройти сутки, и перенос сажал бы прокси за давно истёкшее.
  • Сохраняются только HasEverAnswered = SuccessCount > 0 || IsBelievedAlive («believed» — вердикт этой сессии, а без него прошлой). Прогрев обрывается рано, поэтому большинство запомненных заканчивают сессию непроверенными — строгое Health == Alive стёрло бы накопленный список за пару запусков.
  • Select и Next зарезервированы для CA1716 — метод стратегии называется Pick.

Статистика на «Обзоре»

DashboardViewModel держит сводку пула и обновляет её по событию IProxyPool.Changed с throttle 250 мс — событие приходит на каждый исход лизы и на каждую пробу. «Живых» на карточке — это LiveCount, то же число, что читает гейт сбора; RefreshProxyStats() публичен, чтобы тесты не ждали throttle.