Python-разработчик
110 задач, из них 12 на код с автопроверкой. Условие и варианты ответа открыты всем; проверка, подсказка и разбор — в клубе.
Работа с коллекциями
Типы данных
Python и асинхронность
- Изменяемый список как значение по умолчанию: что напечатает второй вызов функции
- Вызов async-функции без await: что окажется в переменной
- Ключ словаря-кэша: почему падает вторая строка
- Нарезка идентификаторов на пачки для внешнего API
- Срез как копия списка словарей: что окажется в исходных данных
- Пять запросов к внешнему API в цикле с await: почему async не дал ускорения
- Пересчёт агрегатов в четырёх потоках не ускорился: в чём причина
- Вызов asyncio.run внутри обработчика FastAPI падает с RuntimeError
- Один из десяти запросов в asyncio.gather упал, и пропали результаты всех остальных
- Синхронизация 20 тысяч товаров через gather уронила API поставщика
- Синхронный HTTP-клиент в async-эндпоинте: почему тормозит весь сервис, а не одна ручка
- Проверка баланса и списание в async-функции: откуда взялся отрицательный баланс
- Фоновая отправка аналитики через create_task иногда не выполняется
- Воркер не останавливается при выключении сервиса и убивается по таймауту
REST API и валидация данных
- Сервис отвечает 200 OK с телом об ошибке: чем это мешает клиентам и мониторингу
- В теле запроса нет обязательного поля схемы: что увидит клиент
- Отмена заказа через GET /orders/17/cancel: чем опасен такой контракт
- Какой ответ вернуть на успешное создание заказа через POST /orders
- Пользователь с действующим токеном пытается открыть чужой заказ
- После сохранения профиля пропали телефон и город: разбор запроса PUT
- В ответе API оказалось поле hashed_password: как оно туда попало
- Какое изменение контракта сломает уже установленные версии мобильного приложения
- Разбор и проверка параметров пагинации из query-строки
- Клиент прислал поле с опечаткой, получил 200, а email так и не обновился
- Запрос из фронтенда падает с ошибкой CORS, а через curl всё работает
- Клиент повторил POST оплаты после таймаута, и заказ оплатили дважды
- Построение выгрузки за три минуты внутри POST-запроса: почему клиент получает 504 и дубли
- Итог по платежам в ответе API приходит как 10.199999999999999
- Два менеджера редактировали один заказ, и изменения первого пропали
PostgreSQL, ORM и оптимизация запросов
- Список из 200 заказов делает 201 запрос к базе
- Поиск по email в таблице на 5 млн строк занимает две секунды
- Перевод между счетами: деньги списали, но не зачислили
- Запрос активных пользователей возвращает ноль строк, хотя они есть
- В отчёте 1200 заказов, а по запросу с COUNT по промокоду выходит 300
- Индекс на email есть, но запрос по-прежнему читает всю таблицу
- Составной индекс (company_id, created_at) не помогает фильтру только по дате
- Двадцатая страница списка открывается мгновенно, а двухтысячная — четыре секунды
- Страница выдачи с курсором вместо OFFSET
- Два воркера взяли из таблицы одну и ту же задачу и отправили письмо дважды
- Обращение к позициям заказа после выхода из сессии SQLAlchemy падает с ошибкой
- После добавления восьми индексов отчёт ускорился, а ночной импорт замедлился втрое
- Миграция с CREATE INDEX остановила запись в боевую таблицу на десять минут
- Пока банк отвечает на запрос оплаты, остальные операции с заказом висят
- Миграция с переименованием колонки уронила сервис на время раскатки
Кэш, очереди и надёжность сервисов
- Пользователь сменил имя, а в профиле два дня показывается старое
- Redis недоступен — сервис отвечает 500 на все запросы, хотя база жива
- Сервис заказов падает вместе с сервисом уведомлений
- Через месяц после запуска кэша Redis перестал принимать записи
- Стабильный ключ кэша для выдачи с фильтрами
- В фоновую задачу передали объект заказа: почему так делать нельзя
- Разные пользователи видят в списке чужие заказы: разбор ключа кэша
- Добавили пять потребителей в группу, а отставание по топику не уменьшилось
- Запросы несуществующих товаров проходят мимо кэша и грузят базу
- Фоновая задача иногда не находит в базе только что созданный заказ
- Каждый час ровно в одну и ту же минуту база получает всплеск нагрузки
- Заказ в базе есть, а событие об оплате не получил никто
- После повторной доставки сообщения клиенту дважды списали деньги
- Истёк один ключ с тяжёлым отчётом, и база легла под сотнями одинаковых запросов
- Выгрузка на полтора часа запускается вторым воркером, пока первый не закончил
Python: типы, ООП и структуры данных
- Отменённые заказы удаляют прямо в цикле, а один остаётся в списке
- Функция дописала тег, и он появился в списке у вызывающего кода
- Две суммы с одинаковыми полями оказались не равны друг другу
- Счётчик заказов по статусам
- Поле объявлено как float, а в него приехала строка из JSON
- У наследника пропало поле, объявленное в родительском классе
- Сборка отчёта на 200 тысяч строк идёт минуты вместо секунд
- Дедупликация выгрузки по ключу с сохранением порядка
- Наложение пользовательских настроек на конфиг по умолчанию
- Класс отчёта со списком по умолчанию не даёт импортировать модуль
- После добавления сравнения по коду объект перестал класться в множество
- Схлопывание пересекающихся интервалов дежурств
Тестирование: pytest, фикстуры, моки
- Тест на расчёт скидки зелёный, хотя функция возвращает неправильную сумму
- Тест курса валют через раз падает на CI и никогда — у разработчика
- Упал тест на пять сценариев валидации, и видно только первый
- Проверка срока действия токена, которую можно протестировать
- Тесты проходят по одному, а вместе падают в зависимости от порядка
- Юнит-тест с замоканной сессией ORM зелёный, а регистрация в проде падает
- Покрытие функции 100%, а обычные клиенты получили скидку VIP
- Повтор вызова внешнего сервиса с подменяемой зависимостью
- Фейковый репозиторий пользователей для тестов сервиса
- Замокали requests.get, а тест всё равно ходит в сеть
- Тест «заказ создан сегодня» падает на CI только по ночам
- Мок асинхронного клиента падает на await с TypeError
Docker, CI/CD и эксплуатация сервиса
- Каждая сборка образа заново ставит все зависимости, даже после правки одной строки
- Контейнер запущен с пробросом порта, но сервис снаружи не отвечает
- Ключ платёжного API записали в ENV внутри Dockerfile
- В проде образ с тегом latest, и после сбоя непонятно, на что откатываться
- docker compose up: API падает на старте, потому что база ещё не готова
- Логи сервиса пишутся в файл внутри контейнера и не видны в системе сбора логов
- CI зелёный, а собранный через день образ падает при импорте библиотеки
- После добавления метки user_id в метрику Prometheus съел всю память
- Дежурные перестали реагировать на алерты из Sentry
- База легла на минуту, а оркестратор перезапускал сервис по кругу ещё двадцать
- На каждом деплое клиенты получают несколько секунд ответов 502
- Миграции запускаются при старте каждого пода, и релиз иногда падает
Микросервисы и обмен событиями
- Пять сервисов с доступностью 99,9% в синхронной цепочке оформления заказа
- Сервис каталога переименовал колонку, а упал сервис заказов
- Запрос упал где-то в цепочке из четырёх сервисов, а логи не связать
- Воркер упал посреди обработки, и сообщения из очереди пропали навсегда
- Событие «заказ доставлен» обработано раньше, чем «заказ оплачен»
- Сервис оплаты притормозил, а нагрузка на него выросла в 27 раз
- Оплата не прошла, а товар на складе так и остался зарезервирован
- После выделения сервиса пользователей страница заказов делает 50 HTTP-запросов
- Одно битое сообщение остановило обработку всей партиции
- Номер удалённого поля в protobuf отдали новому полю, и старые клиенты сошли с ума
- Из события убрали поле, и три чужих сервиса упали после релиза
- Блокировка в Redis с TTL не помешала двум воркерам списать деньги
