Для успешного выполнения домашних заданий вам потребуется:
-
Создать персональную копию репозитория
Выполните fork данного репозитория на своём аккаунте GitHub — это создаст независимую копию для вашей работы. -
Настроить правила:
- Перейдите в
Settings→Branchesвашего форка - Добавьте правила для ветки
main:Add classic branch protection rule - Установите
Branch name pattern= main - Включите опции:
- Require a pull request before merging
- Require approvals
- Require status checks to pass
- Do not allow bypassing the above settings
- Перейдите в
-
Добавьте ревьюера:
- Перейдите в
Settings→Collaboratorsвашего форка - В поле
Add peopleвведите логин GitHub вашего ментора и нажмите Add. - Теперь этот человек будет иметь доступ к вашему форку и вы сможете назначать его ревьюером в PR, созданных внутри вашего форка.
- Перейдите в
-
Настроить безопасное подключение
Настройте SSH-ключ или получите токен аутентификации для безопасного доступа к репозиторию без ввода пароля. -
Склонировать репозиторий локально
Используйте командуgit cloneдля загрузки репозитория на ваш компьютер. -
Создать рабочую ветку
На основе веткиmainсоздайте новую ветку с произвольным названием для разработки решения. -
Создать go-модуль dz3
go mod init dz3 -
Реализовать решения задач
В созданной ветке напишите код для задач, разместив решения и тестовые примеры в соответствии со структурой проекта, описанной ниже. -
Завершить и проверить решение
После завершения разработки убедитесь, что:- Все тесты проходят успешно
- CI/CD pipeline показывает положительный результат
- Код соответствует требованиям
-
Создать запрос на слияние
Отправьте Pull Request для объединения вашей ветки с веткой main вашего репозитория (а не основного!). -
Получите одобрение ментора
Напишите ментору в телеграмм и дождитесь его обратной связи (возможно придётся исправить!)
Важно: Сохраняйте соответствие структуре проекта и обеспечивайте прохождение всех автоматических проверок перед отправкой работы.
Гайд по созданию персональной копии репозитория и аутентификации есть здесь
.
├── README.md
├── requirements.txt
├── src
│ ├── main.py
│ ├── manager
│ │ ├── manager.py
│ │ └── task.py
│ └── tasks
│ ├── abstract.py
│ ├── file.py
│ └── net.py
├── tests
│ ├── conftest.py
│ └── test_async_queue.py
Реализовать асинхронную очередь задач, которая позволяет выполнять несколько задач параллельно с учётом приоритета и обработки ошибок. Каждая задача должна быть экземпляром класса, наследующего абстрактный класс Task. Реализовать существующих наследников Task, придумать и реализовать свою. Очередь должная работать с любыми наследниками Task, реализованными в соответствии с требованиями.
В реальных системах часто возникает необходимость выполнять множество независимых действий — загрузку файлов, сетевые запросы, чтение данных — действия, которые не нагружают процессор и поэтому могут быть выполнены асинхронно.
Такие задачи обычно связаны не с вычислениями, а с ожиданием внешнего события (например, ответа сервера, чтения файла или записи в базу данных). Вместо того чтобы блокировать поток, программа может в это время выполнять другие задачи.
Самые частые примеры таких задач:
-
Чтение и запись файлов на диск (например, загрузка логов или отчётов);
-
Сетевые запросы к API (получение данных с веб-сервисов, REST-запросы);
-
Загрузка или скачивание файлов из интернета;
-
Обращение к базе данных через асинхронные драйверы (например, asyncpg, aiomysql);
-
Асинхронная отправка уведомлений или сообщений (например, в Telegram, Slack, RabbitMQ);
Асинхронный подход позволяет эффективно использовать систему во время ожидания и масштабировать систему без необходимости создавать десятки потоков или процессов.
Необходимо реализовать систему из нескольких модулей:
- Абстрактная задача Task
Определяет структуру и интерфейс любой задачи. Конкретные задачи должны наследоваться от этого класса.
Содержит:
- id: UUID — уникальный идентификатор задачи;
- priority: int — приоритет (0–100, чем выше, тем раньше выполняется);
- абстрактный метод execute(), выполняющий задачу.
- Очередь AsyncTaskQueue
Поддерживает асинхронное выполнение задач с ограниченным числом воркеров в соответствии с заданным приоритетом. Воркер -- отдельная корутина, которая выполняет задачи из очереди.
-
Примеры конкретных задач:
-
FileReadTask: асинхронно читает файл с диска;
-
HttpDownloadTask: скачивает файл по URL;
-
Ваша собственная задача.
-
-
Все задачи должны быть асинхронными, т.е. они не должны блокировать цикл событий.
-
Все задачи должны иметь уникальный идентификатор.
-
Все задачи должны иметь приоритет от 0 до 100.
-
Операции очереди должны быть безопасными относительно асинхронного выполнения (но не обязательно потокобезопасными).
-
Очередь должна работать с любыми наследниками Task, реализованными в соответствии с требованиями.
-
Очередь должна корректно останавливаться, заканчивая выполнение всех задач и завешением воркеров.
-
Простейший способ реализовать приоритетную очередь -- список + bisect или heapq.
-
Для асинхронной работы с сетью лучше использовать aiohttp.
-
Для асинхронной работы с файлами лучше использовать aiofiles.
-
Для обеспечение безопасности и оповещения о выполнении чего-либо можно использовать примитивы синхронизации: https://docs.python.org/3/library/asyncio-sync.html