From 1d11cfedf4900e03e229fa6501fbe54e1b2e23fb Mon Sep 17 00:00:00 2001
From: "a.tolstoy" <a.tolstoy@picodata.io>
Date: Fri, 16 Dec 2022 17:07:51 +0300
Subject: [PATCH] docs: fix spotted minor issues

---
 docs/clustering.md | 11 +++---
 docs/discovery.md  | 92 ----------------------------------------------
 docs/install.md    |  2 +-
 3 files changed, 7 insertions(+), 98 deletions(-)
 delete mode 100644 docs/discovery.md

diff --git a/docs/clustering.md b/docs/clustering.md
index 95ff91e1..a0a1368b 100644
--- a/docs/clustering.md
+++ b/docs/clustering.md
@@ -22,11 +22,12 @@ picodata run --instance-id iN --listen iN --peer i1
 (discovery). 
 
 Подробности алгоритма discovery приведены в отдельном
-[документе](discovery.md). В контексте сборки кластера важно лишь
-понимать, что этот алгоритм позволяет не более чем одному инстансу
-(peer'у) создать Raft-группу, т.е. стать инстансом с raft_id=1. Если
-таких инстансов будет несколько, то и Raft-групп, а следовательно и
-кластеров Picodata получится несколько.
+[документе](https://git.picodata.io/picodata/picodata/picodata/-/blob/master/docs/discovery.md).
+В контексте сборки кластера важно лишь понимать, что этот алгоритм
+позволяет не более чем одному инстансу (peer'у) создать Raft-группу,
+т.е. стать инстансом с raft_id=1. Если таких инстансов будет несколько,
+то и Raft-групп, а следовательно и кластеров Picodata получится
+несколько.
 
 Топологией Raft-группы управляет алгоритм Raft, реализованный в виде
 крейта `raft-rs`.
diff --git a/docs/discovery.md b/docs/discovery.md
deleted file mode 100644
index f74db791..00000000
--- a/docs/discovery.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Discovery algorithm
-
-## Входные данные:
-
-- `N` узлов, пока не связанных друг с другом по сети. Связать их предстоит алгоритму.
-- Тем не менее, каждый узел обладает на старте информацией о некоторых его соседях - массиве `initial_peers`, содержащем сетевые адреса узлов (не менее одного).
-
-Алгоритм налагает некоторые ограничение на входные данные, в противном случае результат работы алгоритма может оказаться некорректным. Чтобы обеспечить выполнение результата, у любой пары узлов должен существовать как минимум один общий элемент `initial_peers`.
-
-Здесь стоит сказать пару слов о том, как именно мы будем моделировать сеть. Алгоритм специально составлен таким образом, чтобы его легко было адаптировать под конкретный транспортный протокол, хоть TCP, хоть UDP.
-
-Чтобы не прослыть инфантильными, мы также сразу допускаем, что связность сети может спонтанно нарушаться. Любое сообщение может:
-- быть доставлено получателю спустя неопределённое время,
-- возможно бесконечно малое,
-- а возможно и бесконечно никогда.
-
-Мы хотим, чтобы алгоритм был полезен на практике. И такое предположение, несомненно, благоприятно скажется на способностях алгоритма не разбиться о суровую реальность, где сервера иногда ~~простужаются~~ перегреваются и выгорают целыми датацентрами.
-
-В тоже время алгоритм совершенно не подготовлен к решению задачи о византийских генералах. Акцент в первую очередь делается на отказоустойчивости к ошибкам пользователя, а не злонамеренности генералов. Это призвано упростить процесс инициализации рафт группы (который в худшем случае можно и перезапустить на этапе подготовки к эксплуатации, в отличие от генералов). Византийская отказоустойчивость, если это необходимо, должна обеспечиваться другим протоколом.
-
-## Результат:
-
-Результатом работы этого распределенного алгоритма является единственное булево значение `i_am_bootstrap_leader`. Мы ожидаем (и заверяем вас), что, пока входные параметры не нарушают наложенных ограничений, не более одного узла будущего кластера присвоят себе эту медальку. Я бы хотел, чтобы "не меньше" тоже было равно одному, но, увы, в условиях полной сетевой изоляции ответ будет ноль, и никакой онлайн-вечеринки не состоится.
-
-И опять, в угоду пользовательского опыта, алгоритм не пытается заполучить больше информации о будущем кластере. В противном случае это потребовало бы делать дополнительные предположения о сетевой связности, и это могло негативно сказаться на удобстве эксплуатации решения. Данный алгоритм надеется на лучшее (один бутстрап лидер), оставаясь готовым к худшему (ноль бутстрап лидеров).
-
-## Собственно сам алгоритм
-
-### **Шаг 0.1**
-
-Как уже упоминалось раньше, каждый узел _i_ инициализирует массив известных адресов `known_peers[i] = initial_peers[i]` (со значениями, предоставленными пользователем).
-
-### **Шаг 0.2**
-
-Каждый узел _i_ генерирует случайный идентификатор (`guid[i]`), вероятность коллизии которых мы предполагаем равной нулю. Это требование совсем не сложно выполнить на практике.
-
-### **Шаг 1**
-
-Каждый узел _i_ проводит раунд запросов номер `r` - отправляет по всем известным адресам `known_peers[i][m]` сообщение `("discovery_req", m, known_peers[i])`. Параметр `m` представляет собой всего лишь индекс адресата в массиве `known_peers[i]`. Единственная его роль в алгоритме - быть возвращённым в ответе, чтобы можно было сопоставить ответ с конкретным адресом. Впрочем, его можно вообще опустить, если эту функциональность предоставляет используемый транспортный протокол.
-
-### _Меж двух шагов_
-
-Получив сообщение `("discovery_req", m, known_peers[i])`, узел (_j_) проверяет своё состояние.
-
-Если на данный момент лидер уже выбран и известен, то отправляет в ответ сообщение `("discovery_finished")`.
-
-В противном случае обновляет свой массив `known_peers[j] = known_peers[i] \/ known_peers[j]`. Ответ содержит `("discovery_resp", m, known_peers[j], guid[j])`.
-
-Здесь делается ещё одно допущение о том, что используемый транспортный протокол обладает функцией "отправки ответа". Оба TCP и UDP такой функциональностью обладают.
-
-### **Шаг 2** (Возвращаясь к узлу _i_ - отправителю запроса)
-
-Yaroslav Dynnikov, [08/04/2022 22:18]
-
-
-Получив ответ `("discovery_finished")` алгоритм завершает свою работу - задача выполнена. `i_am_bootstrap_leader[i] = false`.
-
-Получив ответ `("discovery_resp", m, known_peers[j], guid[j])`, узел (_i_), как и в случае обработки `discovery_req`, обновляет свой массив `known_peers[i] = known_peers[i] \/ known_peers[j]`. Далее полученный ответ сопоставляется с адресатом `known_peers[i][m]`. Если в массиве `known_peers[i]` остались ещё не ответившие адресаты, алгоритм приостанавливается до получения следующего сообщения.
-
-Если ответ содержит ошибку протокола транспортного уровня, запрос повторяется с некоторым интервалом до тех пор, пока не будет получен внятный ответ.
-
-Если к концу этого шага были обнаружены новые адресаты, алгоритм начинает новый раунд запросов `r+1` и возвращается к шагу 1.
-
-### **Шаг 3**
-
-Если вдруг лидер до сих пор не известен, то к этому моменту каждому узлу _i_ становится известна полная карта `known_peers[i][m] -> guid[m]`.
-
-Если вдруг `guid[i] == min(guid)`, то узел понимает, что `i_am_bootstrap_leader[i] = true`, и с этих пор перестаёт изменять внутреннее состояние, и отвечает на все запросы `("discovery_finished")`.
-
-Если же, напротив, `guid[i] != min(guid)`, то `i_am_bootstrap_leader[i] = false`.
-
-### Доказательство
-
-Корректность алгоритма проще всего доказать от противного. Предположим, что в какой-то момент узел _i_ решил, что `i_am_bootstrap_leader[i] == true`, в то время как уже существовал `i_am_bootstrap_leader[j] == true` (и при этом `i != j`).
-
-Так как на третьем шаге оба узла вычисляют `min(guid)` идентичным оразом, то отличаться должны были сами таблицы `guid`.
-
-При этом массив `known_peers[j]` заведомо не содержал адрес _i_ в момент принятия решения, но содержал свой адрес _j_, иначе бы не выполнилось условие `guid[j] == min(guid)`. Аналогично, `known_peers[i]` точно содержал _i_.
-
-В то же время `known_peers[i]` не мог содержать _j_, иначе _i_ не смог бы получить от _j_ ответ `("discovery_resp")` и не “выдать” себя.
-
-Таким образом _i_ и _j_ не должны были в момент принятия решения ничего знать друг о друге.
-
-Но так как у _i_ и _j_ по условию должен быть как минимум один общий "сосед", назовём его _z_, он также должен был обоим _i_ и _j_ дать ответы `("discovery_resp")`. Противоречие заключается в том, что _z_ пришлось бы одному из двух узлов в ответе `("discovery_resp")` сообщить о существовании второго, покуда обработка запросов выполняется атомарно.
-
-### Возможные оптимизации
-
-Основная часть алгоритма изложена так, чтобы быть максимально простой. Тем не менее, это не исключает наличия нескольких полезных оптимизаций, которые нисколько не влияют на результат, хотя позволяют сделать пользовательский опыт приятнее.
-
-Начинать новый раунд на втором шаге не возбраняется сразу после обнаружения нового адресата. Не обязательно для этого дожидаться всех ожидаемых ответов.
-
-После завершения работы алгоритма, с сообщениями `("discovery_finished")` можно рассылать информацию об адресе лидера, о `known_peers`, или любую другую необходимую, которую хотелось бы синхронизировать. Так как единственность лидера доказана, остальные узлы могут ему верить, если конечно никто больше не возьмётся её модифицировать, а мы договорились не рассматривать византийские сценарии.
diff --git a/docs/install.md b/docs/install.md
index 0a1c5db8..c532f8b1 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -146,7 +146,7 @@ Picodata может создать кластер, состоящий всего
 picodata run
 ```
 
-Можно добавлять сколько угодно последующих инcтансов — все они будут подключаться к этому кластеру. Каждому интансу следует задать отдельную рабочую директорию (параметр `--data-dir`), а также указать адрес и порт для приема соединений (параметр `--listen`) в формате `<HOST>:<PORT>`. Фактор репликации по умолчанию равен 1 — каждый инстанс образует отдельный репликасет. Если для `--listen` указать только порт, то будет использован IP-адрес по умолчанию (127.0.0.1):
+Можно добавлять сколько угодно последующих инcтансов — все они будут подключаться к этому кластеру. Каждому инстансу следует задать отдельную рабочую директорию (параметр `--data-dir`), а также указать адрес и порт для приема соединений (параметр `--listen`) в формате `<HOST>:<PORT>`. Фактор репликации по умолчанию равен 1 — каждый инстанс образует отдельный репликасет. Если для `--listen` указать только порт, то будет использован IP-адрес по умолчанию (127.0.0.1):
 
 ```
 picodata run --data-dir i1 --listen :3301
-- 
GitLab