31 lines
2.2 KiB
Markdown
31 lines
2.2 KiB
Markdown
|
# retryupdate
|
|||
|
|
|||
|
В этой задаче, вам нужно познакомиться с паттернами обработки ошибок в golang.
|
|||
|
|
|||
|
Вам дан клиент вымышленного сервиса. Сервис хранит отображение `key -> (value, version)`,
|
|||
|
где `key` и `value` - это обычные строки. А `version` - уникальный идентификатор, который сгенерировал
|
|||
|
клиент.
|
|||
|
|
|||
|
Вам доступны два метода - `Get` и `Set`. Поведение методов описано в пакете `kvapi`.
|
|||
|
|
|||
|
Методы могут завершаться с различными ошибками. Ошибки описаны в том же пакете.
|
|||
|
|
|||
|
Вам нужно реализовать функцию `UpdateValue`, которая принимает ключ и функцию
|
|||
|
для "обновления" значения. Функция должна обновить значение по ключу, правильно обрабатывая
|
|||
|
ошибки, возникающие в процессе работы.
|
|||
|
|
|||
|
- Если ключ не нашёлся, нужно передать в `updateFn` значение `nil`.
|
|||
|
- Если произошла ошибка доступа, то нужно сразу выходить.
|
|||
|
- Если произошла ошибка внутри updateFn, то нужно сразу выходить.
|
|||
|
- Если случился конфликт при записи, и значение изменилось с момента последнего чтения,
|
|||
|
то нужно прочитать новое значение и попробовать заново.
|
|||
|
- Любые другие ошибки из `api` нужно "ретраить" бесконечно.
|
|||
|
|
|||
|
Функция должна минимизировать число запросов к API.
|
|||
|
|
|||
|
Для генерации нового `uuid` на клиенте, используйте вызов `uuid.Must(uuid.NewV4())`.
|
|||
|
|
|||
|
Большую цепочку `if`-ов удобнее писать через `switch`.
|
|||
|
|
|||
|
Для выхода из вложенных циклов вам помогут [loop labels](https://golang.org/doc/effective_go.html#switch).
|