Sobes.tech
Junior — Senior

Ускорение выполнения через параллельные запросы

livecode

Vazifa holati

Необходимо доработать функцию Do так, чтобы её выполнение занимало около 10 мс независимо от количества переданных пользователей. Каждый вызов fetchByName имитирует задержку в 10 мс. Функции main и fetchByName менять нельзя – вся оптимизация должна быть реализована внутри Do.

package main

import (
    "context"
    "fmt"
    "math/rand"
    "sync"
    "time"
)

type User struct {
    Name string
}

func main() {
    fmt.Println(Do(context.Background(), []User{{"aaa"}, {"bbb"}, {"ccc"}, {"ddd"}, {"eeee"}}))
}

// fetchByName изменять нельзя
func fetchByName(ctx context.Context, userName string) (int, error) {
    time.Sleep(10 * time.Millisecond) // имитация сетевого похода
    return rand.Int() % 100000, nil
}

// все изменения должны происходить в этой функции
func Do(ctx context.Context, users []User) (map[string]int, error) {
    result := make(map[string]int)
    var mu sync.Mutex
    var wg sync.WaitGroup
    errCh := make(chan error, 1)

    for _, usr := range users {
        wg.Add(1)
        go func(u User) {
            defer wg.Done()
            id, err := fetchByName(ctx, u.Name)
            if err != nil {
                select {
                case errCh <- err:
                default:
                }
                return
            }
            mu.Lock()
            result[u.Name] = id
            mu.Unlock()
        }(usr)
    }

    wg.Wait()
    close(errCh)

    if err, ok := <-errCh; ok {
        return result, err
    }
    return result, nil
}