Разработка функциональности автоматического обновления статуса задачи в ЦАП #57
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Демонстрация
dtaa.mp4
Как оно работает?
Фрагмент HTML со статусом задачи был выделен в отдельный шаблон student/task_status.jinja, student/task.jinja безусловно его включает в себя. Кроме того, этот статус теперь находится в div с id равным task-status. POST запрос на
/group/<int:gid>/variant/<int:vid>/task/<int:tid>/wsпри успешном отправлении задачи перенаправляет на себя же.Была добавлена ручка
/group/<int:gid>/variant/<int:vid>/task/<int:tid>/wsс WebSocket. При подключении он ждёт пока данная задача не будет проверена, после чего отправляет HTML с новым статусом задачи и закрывает сокет.JS на
/group/<int:gid>/variant/<int:vid>/task/<int:tid>, который добавляется на уровне шаблона только если задача проверяется, подключается к выше упомянутому WebSocket и заменяет содержимое#task-statusна каждое пришедшее сообщение.Почему оно так работает?
Было 3 варианта решить эту задачу:
Так как для последних двух способов необходимо держать "живой" запрос, которому необходимо занимать один из потоков у WSGI-сервера, придётся увеличить пул воркеров и потоков у каждого воркера, иначе эти долгоживущие запросы имеют вероятность повесить сервер. Для избежания этого в текущей реализации сервер закрывает сокет либо если задача не отправлена, либо как только она проверена.
В реализации с WS это проще вынести в отдельный процесс, а reverse-proxy вроде nginx будет распознавать запросы к этому WS и перенаправлять их на этот процесс. Это снизит нагрузку на основное приложение и избавит от необходимости увеличивать количество потоков.
Что стоит изменить в будущем?
Добавить PubSub
На данный момент сервер проверяет статус задачи простым поллингом в цикле без каких либо задержек. Можно либо добавить Redis/Valkey как ещё один сервис, либо поддерживать только PostgreSQL и использовать его аналогичные способности. SQLAlchemy в теории поддерживает похожий функционал, но он не очень хорошо работает с multiprocessing, поэтому им не воспользовался.
Тесты
Я также не нашёл способ тестировать WS из pytest, поэтому тесты не добавил, но
make coverageмне говорит, что/group/<int:gid>/variant/<int:vid>/task/<int:tid>в целом не покрыт тестами, так что считаю своё решение чуточку более обоснованным (:Минимизация
static/js/autoreload.jsРуками это не очень хорошо делать, поэтому надо придумать способ внедрить это в сборочную систему, который видимо сейчас тоже нет.