Комментарии 3
Спасибо за статью.
Немного подушню :-) В воркерах я бы добавил проверку, что канал не был закрыт, и прокинул бы контекст дальше в целевую функцию (ну и обрабатывать отмену там тоже), а то в случае если контекст будет отменен после того, как мы провалились в функцию, воркер не закончит работу пока она не доработает.
func worker(ctx context.Context, jobs <-chan Job) {
for {
select {
case job, ok := <-jobs:
if !ok {
return
}
processJob(ctx, job)
case <-ctx.Done():
log.Println("Worker shutting down")
return
}
}
}
func processJob(ctx context.Context , job Job) {
ch := make(chan {}struct)
go func() {
// Вот тут что-нить тяжелое
close(ch)
}
select {
case <-ch:
return
case <-ctx.Done():
return
}
}
func withRetry(fn func() error, maxRetries int, backoff time.Duration) error {
for i := 0; i < maxRetries; i++ {
if err := fn(); err == nil {
return nil
}
if i < maxRetries-1 {
select {
case <-time.After(backoff * time.Duration(i+1)):
// Exponential backoff
}
}
}
return fmt.Errorf("exceeded max retries")
}
Здесь ошибка в комментарии, т.к. реализован линейный backoff.
Экспоненциальный делей можно реализовать вот так:
delay := backoff * time.Duration(1 << i)
Конкурентность и параллелизм не одно и тоже! Каналы это инструмент для контроля конкурентности, в не параллелизма.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Каналы(channels) в Go