Как в Go асинхронно выполнять поступающие задачи и выводить конечный результат?

Имеется N однотипных задач. Необходимо выполнить их асинхронно и записать результаты.
Для выполнения задачи раньше я запускал N горутин с разными параметрами для каждой задачи, а результаты складывал в MAP
Дожидался выполнения всех функций с помощью sync.WaitGroup и потом уже генерировал ответ.

Теперь появилась необходимость дополнять список из N задач прямо из уже работающей функции.
Например запустилось 10 горутин, и внутри одной горутины появилась необходимость выполнить еще 2 задачи. (В какой горутине, сколько новых задач нужно будет добавить и нужно ли будет вообще что-то добавлять - заранее знать не можем) То есть общее количество становится 12, и эти вот две дополнительных задачи как-то должны сразу начать выполнение не дожидаясь окончания первоначально запущенных 10 задач.
И уже надо дожидаться выполнения всех 12-ти задач.
Также каждая из двух новых задач в процессе выполнения может также захотеть запустить M задач.

А в конечном итоге, если каждая задача выполнилась и не запустила ни одной новой задачи - завершить ожидание выполнения задач и ответить пользователю.

Возможно ли такое?
Есть ли возможность реализовать подобное с помощью той же sync.WaitGroup или необходимо уже подключать каналы?
Какие каналы использовать - с буфером или без? Если с буффером, то с каким, если неизвестно число задач.
Пробовал сделать канал с буфером большого размера. Отправил в него нужные данные.
В другой подпрограмме делаю range по каналу - запускаю задачи асинхронно, и внутри некоторых задач шлю в канал еще сообщение о новом задании, но как мне отследить в таком случае, что они уже все выполнены и не требуется выполнять новых заданий?

И может есть уже готовое решение, как реализовать подобное.
Жду подсказок.
  • Вопрос задан
  • 272 просмотра
Решения вопроса 1
@RidgeA
Я бы сделал так.
1. Есть канал куда попадают все задачи.
2. Есть горутина, которая разгребает канал и на каждоее сообщение из канала запускает горутину для обработки сообщения.
3. При необходимости эта горутина ставит сообщения в тот же канал.
4. При запуске горутины-обработчика добавлять в wait group и не забыть 'defer wg.Done()'

Вот как-то так: https://play.golang.org/p/z0fS5O8ynSI
Не уверен, что это хороший код, но общую идею показть должен.
Размер буфера - то максимально возможное количество задач, которые могут прийти в качестве подзадач (с учетом вложенности, если у подзадачи могут быть свои подзадачи + 1 (на текущую задачу)
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Sly_tom_cat
@Sly_tom_cat
.
Вам похоже сюда: https://gobyexample.com/worker-pools

Ну, то есть там классический пример на известное количество задач, но у вас может быть свой счетчик задач (только надо что-то из асинхронных типов данных использовать).

Новые job-ы лучше добавлять в теле самих job-ов, которые порождают новые.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы
Xsolla Пермь
от 50 000 до 120 000 руб.
Dialog Москва
от 180 000 до 280 000 руб.
Cryptology Москва
от 2 500 до 5 000 usd.