Pull to refresh
1
Алксандр Егунов@crymans

User

Send message

Мощный ресёрч, особенно про canary и две копии std в одном процессе.

Есть небольшое уточнение по поводу FFI и extern "C". Вы пишете, что в 1.81 границу закрыли окончательно и теперь это принудительный abort. Но разве это спасает от ситуации, когда Сишный код, вызванный из Rust, сам бросает longjmp (или плюсовый код кидает эксепшен через extern "C" обратно в раст)? Насколько я помню, Itanium ABI в таких случаях все равно может сломать стек, если на пути окажутся фреймы раст без правильного landing pad. То есть C-unwind обязателен не только для проброса паники наружу, но и для безопасного пролета чужого unwind внутрь раст кода?

Идея с self-service отличная, но есть пара инфраструктурных нюансов по реализации:

  1. Под каким пользователем запущен сам фласк? Если сервис работает от root, чтобы иметь права на os.kill — это очень опасный паттерн для веб-приложения. Гораздо безопаснее запускать сам Flask (через systemd/gunicorn) строго под юзером hcl. Тогда проверка if owner != PROCESS_OWNER становится просто страховкой от ошибок логики — ядро ОС на уровне прав само не даст фласку убить чужие процессы, даже если кто-то подделает запрос.

  2. Вы пишете, что выбрали SIGTERM как "менее жесткий вариант". Но если флоучарт реально намертво «завис» (например, случился дедлок или процесс повис на I/O-операциях), он с большой вероятностью просто проигнорирует мягкий SIGTERM, и процесс останется висеть. В таких хелперах обычно реализуют паттерн graceful shutdown: отправляют SIGTERM (у psutil для этого есть удобный метод proc.terminate()), ждут пару секунд через proc.wait(timeout=3), и если процесс всё ещё жив — добивают уже жестким proc.kill(). Иначе вашим инженерам всё равно придется периодически заходить и делать kill -9 руками.

Свой gRPC-wire вместо стандартного стека — это круто, но есть один архитектурный нюанс по безопасности.

В секции про Tsak вы пишете: «берётся самый правый хоп X-Forwarded-For, тот, который дописал доверенный прокси и который клиент подделать не может».

Если перед вашим приложением стоит цепочка балансировщиков (например, внешний Anti-DDoS -> ваш краевой Nginx), то самым правым хопом в заголовке окажется IP-адрес внешнего шлюза, а не реального атакующего. Выдав бан по этому IP при переборе, вы положите доступ вообще всем легитимным пользователям, идущим через этот узел.

Безопаснее парсить заголовок X-Forwarded-For справа налево, последовательно отбрасывая статические IP-адреса ваших собственных доверенных прокси. Первый же неизвестный адрес в цепочке с конца — это и есть настоящий IP клиента.

Травма от джанговских строк очень понятна)

Но фишка современных DI на питоне (той же Dishka) как раз в том, что там под капотом нет никакой строковой магии. Всё резолвится исключительно по type hints.

Вы просто указываете в init юзкейса зависимость вида repo: UserRepository. В итоге IDE, mypy и автокомплит работают идеально, потому что типы прописаны явно и строго. Так что компромиссов с типизацией тут не будет, реально советую потыкать.

Запихивать репозитории в TransactionManager через @property — это прямой путь к god-object. При росте приложения этот класс раздует, и его придется модифицировать при добавлении каждой новой таблички (явное нарушение OCP). Гораздо изящнее разруливать это через нормальный DI-контейнер (ту же Dishka). Провайдишь сессию куда надо, а управление транзакцией вешаешь декоратором прямо на юзкейс. И базовый класс чистый, и бойлерплейта меньше.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity

Specialization

Бэкенд разработчик, Веб-разработчик
Младший
From 150,000 ₽
Git
Docker
Linux
Python
Английский язык
ООП
Базы данных
Nginx
Высоконагруженные системы
REST