Как сделать свой Future-Promise или жизненный цикл велосипедов в продакшене
Build your own Future, they said.
It will worth the hassle, they Promised.
That is how I should Function, I was told.
It is the main Task of my life, prophecy declared.
said. It will worth the hassle, they Promised. That is how I should Function, I was told. It is the main Task of my life, prophecy declared. Денис Кормалев Санкт-Петербург, 2018
на еще два десятка (перенос использующихся решений с легаси) • Постоянное обновление общих механизмов • Основная логика основана на сочетании информации от разных веб-сервисов • Основной веб-сервис (90% всех данных) очень медленный • Нередко можно забирать данные с нескольких сервисов (или даже от одного сервиса) одновременно, не дожидаясь других ответов • Очень много однообразного кода на обслуживание работы с ответами от сервисов
таск шедулере • Шедулер: • Выполняет задачи в фоновых потоках • Позволяет из одного таска вызвать другой или другие • Позволяет ждать таск • Позволяет ожидать асинхронные вызовы, которые присылают ответ через сигнал • Абсолютное большинство данных на бекенде – через shared pointer или Qt контейнеры
количестве потоков • На каждый таск создается новый поток • Дополнительные потоки для обслуживания • std::async + std::future приводят к дополнительным проблемам • Возвращать ошибки не то, чтобы очень легко • Возвращать данные тоже • При параллелизации приходится городить излишние структуры
требует дополнительной поддержки • Нужно упростить работу с возвратом результатов и ошибок • Нужно уменьшить количество лишнего кода для описания логики • Нужно перейти на пул потоков • Слишком мало багов осталось в коде за три с лишним года работы TaskChain, нужны новые
if err != nil • Все еще спасибо, нет • Exceptions • Оверхед при использовании • Исключения для исключительных ситуаций, не для управления выполнением программы • Either • Уже лучше, но приведет к слишком большому объему кода • EitherT • Наш кандидат*
таска – пытаемся шедулить • На каждое завершение таска – пытаемся шедулить • Пока нет тасков – спим в wait condition • Треды в пуле создаются, пока не достигли максимума • Запуск таска возвращает Future • Возможность создания подпулов
• Custom – отдельные подпулы с задаваемым пользователем лимитом • Intensive – подпул, ограниченный по количеству ядер • ThreadBound – гарантирует что все таски с одинаковым лейблом будут запущены в одном потоке
отмены • Отмена действия только до преобразований • Иначе нарушается гарантия иммутабельности преобразований • Минимальная синтаксическая нагрузка при неиспользовании