30 lines
2.2 KiB
Markdown
30 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).
|