Спроектировать worker pool
Вопрос
Напишите вслух worker pool: N воркеров обрабатывают задачи из списка, результаты нужны в исходном порядке, первая ошибка должна остановить всё, есть общий таймаут.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Контекст с таймаутом и отменой при первой ошибке (errgroup.WithContext или свой cancel)
Канал задач с индексами, N горутин читают его в цикле
Результат пишется по индексу в заранее созданный слайс
Отправка задач в select с ctx.Done, закрытие канала задач после отправки
Ожидание через WaitGroup или g.Wait, возврат первой ошибки
Проверка -race, тест на ошибку и таймаут
Что могут спросить следом
- Что изменится, если задач бесконечный поток?
- Как сделать retry с backoff для отдельных задач?
Разбор
Создаю ctx, cancel := context.WithTimeout(parent, d) и группу g, ctx := errgroup.WithContext(ctx). Результаты храню в res := make([]Result, len(tasks)). Канал jobs chan int с индексами. Запускаю N воркеров через g.Go: каждый в цикле читает индекс, обрабатывает tasks[i] с ctx и пишет res[i]; при ошибке возвращает её, errgroup отменит ctx, и остальные выйдут. Отдельной задачей в группе отправляю индексы: каждая отправка в select с ctx.Done(), после цикла close(jobs). Затем if err := g.Wait(); err != nil { return nil, err }. Порядок сохраняется за счёт индексов, гонки нет, потому что ячейки разные. Без errgroup то же самое на WaitGroup, sync.Once для первой ошибки и cancel. Для бесконечного потока вместо слайса результатов канал результатов и graceful остановка по ctx. Проверяю тестами под -race, включая сценарий с ошибкой в середине и истёкшим таймаутом.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
singleflight и лавина на кеш
Следующий вопрос
MapReduce подсчёта слов на горутинах и каналах