Запустите запрос к каждому серверу и читайте результаты до первого успеха. Буфер размером N не даст оставшимся отправителям зависнуть после возврата.
Параллельный запрос документов к нескольким серверам
Запустите запрос к каждому серверу и читайте результаты до первого успеха. Буфер размером N не даст оставшимся отправителям зависнуть после возврата.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо написать функцию, которая одновременно посылает запрос query на N одинаковых серверов, используя функцию search.Search(server, query). Функция должна вернуть первый полученный корректный результат, не ожидая завершения запросов к остальным серверам. Если каждый из серверов вернёт ошибку, следует вернуть ошибку search failed.
search.Search(server string, query string) ([]string, error)
Ответ
Запустите запрос к каждому серверу и читайте результаты до первого успеха. Буфер размером N не даст оставшимся отправителям зависнуть после возврата.
Передайте существующую search.Search как аргумент run, чтобы не привязывать пример к неизвестному пути её пакета.
import "errors"
func SearchFirst(
servers []string,
query string,
run func(string, string) ([]string, error),
) ([]string, error) {
type reply struct {
docs []string
err error
}
replies := make(chan reply, len(servers))
for _, server := range servers {
go func(server string) {
docs, err := run(server, query)
replies <- reply{docs, err}
}(server)
}
for range servers {
r := <-replies
if r.err == nil { return r.docs, nil }
}
return nil, errors.New("search failed")
}
Пустой список также возвращает search failed. Пустой результат без ошибки считается успешным. В данном контракте нет context: уже начатые search.Search нельзя отменить извне. Чтобы они не продолжали ненужную работу или не зависали навсегда, нужна поддержка отмены и таймаута внутри API поиска.