Junior — Senior
77
Добавление механизма повторных попыток в DistributiveGet
Условие задачи
Необходимо улучшить функцию DistributiveGet, внедрив повторные запросы при возникновении любой ошибки, кроме ErrNotFound, пока значение не будет получено.
func DistributiveGet(ctx context.Context, addresses []string, key string) (string, error) {
if ctx.Err() != nil {
return "", ctx.Err()
}
var wg sync.WaitGroup
wg.Add(len(addresses))
valueCh := make(chan string, 1)
notFoundErrCh := make(chan error, 1)
go func() {
wg.Wait()
close(valueCh)
close(notFoundErrCh)
}()
for _, address := range addresses {
go func(address string) {
defer wg.Done()
for i := 0; i < 3; i++ {
value, err := Get(ctx, address, key)
if errors.Is(err, ErrNotFound) {
select {
case notFoundErrCh <- err:
default:
}
return
}
if err != nil {
select {
case <-valueCh:
return
default:
time.Sleep(100 * time.Millisecond)
continue
}
}
select {
case valueCh <- value:
default:
}
return
}
}(address)
}
select {
case v, ok := <-valueCh:
if !ok {
return "", ErrDistributedGetFailed
}
return v, nil
case err, ok := <-notFoundErrCh:
if !ok {
return "", ErrDistributedGetFailed
}
return "", err
}
}