# Планировщик ## Предпосылки В **Bridges** на данный момент есть проблема, связанная с отправкой транзакций. В случае возникновения ошибки при отправке транзакции в сеть, транзакция просто будет потеряна. Рассмотрим случаи, при которых это можно возникнуть: * Потерялось подключение к ноде блокчейна * Установлена низкая максимальная комиссия при отправке транзакции * Указано недоступное кол-во токенов при переводе (закончились токены в контракте, скорее всего требуется пополнение) При возникновении таких ошибок необходимо попытаться повторно отправить транзакции и, возможно, изменить некоторые атрибуты транзакции. Также помимо отправки транзакций, делаются запросы с оповещениями на API фронтэнда. При отправке запросов могут вернуться ответы с неудачными статус кодами. В таких случаях тоже нужно обработать статус код и попробовать сделать повторную отправку запроса. ## Задачи планировщика Планировщик должен уметь откладывать выполнение следующих работ: * Отправка транзакции * Отправка оповещения на API При возникновении ошибки в работе планировщик должен пытаться выполнить работу заново, либо отложить ее выполнения на какой-то период. Также работы могут зависить друг от друга, поэтому нужно задавать последовательность выполнения работ. Например, отправка оповещения должна происходить после отправки транзакции. > **N.B** Задание последовательности также подразумевает, что должна откладываться целая цепочка невыполненных работ. ## Очередь работ ![Диаграмма очереди планировщика](https://i.imgur.com/fjq1Xek.jpg) У планировщика должна быть очередь для работ, которая будет задавать последовательность их выполнения. Рассмотрим, какие операции должны быть доступны у очереди: * Добавление работы в начало * Добавление работы в конец Операция для добавления в начало нужна, т.к. некоторые работы могут быть приоритетными. Например, в случае неудачного отправления транзакции, данная работа должна быть добавлена в начало очереди. Очередь должна хранить работы в **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.** Данная возможность подразумевает, что обработчик работы должен принимать планировщик в качестве параметра для ее реализации. ## Архив работ Данная возможность требуется только в случае, если работа пыталась выполниться повторно множество раз. Например, оотправку транзакции уже передобавляли в очередь несколько раз, тогда стоит отложить выполнение данной работы на некоторое время. Архив по-сути является такой очередью работ, только с одной особенностью работы из этой очереди достаются с определенным промежутком, например, раз в пол часа (данный параметр должен задаваться при создании). Затем работа, которую достали из архива, должна быть добавлена в начало очереди или в конец в зависимости от приоритета. Возможно, сделать несколько архивов, которые откладывают выполнение работ на разное время. Например, один архив откладывает на пол часа, а другой уже на сутки. То есть сначало работу отложили на пол часа, потом перенесли в очередь, произошла неудача, тогда работу переносят в архив с промежутком на сутки.