# Планировщик
## Предпосылки
В **Bridges** на данный момент есть проблема, связанная с отправкой транзакций. В случае возникновения ошибки при отправке транзакции в сеть, транзакция просто будет потеряна.
Рассмотрим случаи, при которых это можно возникнуть:
* Потерялось подключение к ноде блокчейна
* Установлена низкая максимальная комиссия при отправке транзакции
* Указано недоступное кол-во токенов при переводе (закончились токены в контракте, скорее всего требуется пополнение)
При возникновении таких ошибок необходимо попытаться повторно отправить транзакции и, возможно, изменить некоторые атрибуты транзакции.
Также помимо отправки транзакций, делаются запросы с оповещениями на API фронтэнда. При отправке запросов могут вернуться ответы с неудачными статус кодами. В таких случаях тоже нужно обработать статус код и попробовать сделать повторную отправку запроса.
## Задачи планировщика
Планировщик должен уметь откладывать выполнение следующих работ:
* Отправка транзакции
* Отправка оповещения на API
При возникновении ошибки в работе планировщик должен пытаться выполнить работу заново, либо отложить ее выполнения на какой-то период.
Также работы могут зависить друг от друга, поэтому нужно задавать последовательность выполнения работ. Например, отправка оповещения должна происходить после отправки транзакции.
> **N.B** Задание последовательности также подразумевает, что должна откладываться целая цепочка невыполненных работ.
## Очередь работ

У планировщика должна быть очередь для работ, которая будет задавать последовательность их выполнения. Рассмотрим, какие операции должны быть доступны у очереди:
* Добавление работы в начало
* Добавление работы в конец
Операция для добавления в начало нужна, т.к. некоторые работы могут быть приоритетными. Например, в случае неудачного отправления транзакции, данная работа должна быть добавлена в начало очереди.
Очередь должна хранить работы в **Redis** в сериализованном виде. Чтобы в случае падения p2p ноды, можно было восстановить очередь.
Основной сложностью при сохранении работ в **Redis** является хранение параметров. У работы должна быть примерно следующая структура в очереди:
```json
{
jobName: "job_name",
timestamp: "2022-09-09T15:59:60-08:00",
retries: 5,
}
```
Параметр *timestamp* - это время добавления работы в очередь.
Параметр *retries* нужен для того, чтобы контроллировать кол-во уже выполненных попыток. В случае если кол-во попыток изчерпано, тогда выполняется обработка неудачной ситуации.
Также код обработчика работы на Go, должен привязываться по имени работы. То есть должен быть примерно следующий метод или функция.
```go
func RegisterJob(jobName string, h JobHandler)
```
Хранения параметров можно сделать при помощи key/value пар в **Redis**. Только ключ должен быть составным в следующем формате.
```
'params'/job_name/timestamp/param_name
```
> **N.B.** Составные части указанные в одинарных кавычках записываются в ключ как есть. В параметрах без кавычек происходит подстановка. Например, params/send_transaction/..., в случае если имя работы - send_transaction.
При таком хранении код обработчика на Go может считать работы и ее параметры из **Redis** и затем проводить дальнейшую обработку. Возможно, в конце выполнить рекурсивное добавление новой работы в очередь (см. раздел ниже).
## Рекурсивные работы
Рекурсивное выполнение работ - это одна из идей, которая может позволить задать последовательность выполнения работ.
Идея в том, что работа может добавить в очередь планировщика другую работу. При таком подходе, можно задавать целую цепочку рекурсивных вызовов работ. По-сути задается цепочка последовательных вызовов работ, и при неудачном выполенение одной из работ рекурсивный вызов не происходит и вся цепочка работ откладывается.
> **P.S.** Данная возможность подразумевает, что обработчик работы должен принимать планировщик в качестве параметра для ее реализации.
## Архив работ
Данная возможность требуется только в случае, если работа пыталась выполниться повторно множество раз. Например, оотправку транзакции уже передобавляли в очередь несколько раз, тогда стоит отложить выполнение данной работы на некоторое время.
Архив по-сути является такой очередью работ, только с одной особенностью работы из этой очереди достаются с определенным промежутком, например, раз в пол часа (данный параметр должен задаваться при создании).
Затем работа, которую достали из архива, должна быть добавлена в начало очереди или в конец в зависимости от приоритета.
Возможно, сделать несколько архивов, которые откладывают выполнение работ на разное время. Например, один архив откладывает на пол часа, а другой уже на сутки. То есть сначало работу отложили на пол часа, потом перенесли в очередь, произошла неудача, тогда работу переносят в архив с промежутком на сутки.