% vim: set textwidth=64:

\chapter{Сценарии}

\section{Оракул}

\subsubsection{Публикация <<фактов>>}

Оракул стартует и обновляет стейт.

Затем публикует набор <<фактов>>, отсутствующих в известном ему
состоянии.


\section{hbs2-browser}

\subsection{Отображение списка ссылок}

Предполагается, что \term{hbs2-browser}{hbs2-browser} будет отображать
ссылки в виде списка с бесконечным скроллом, с возможностью поиска, с
неким языком запросов.

Для начала поисковой строкой будет являться просто подстрока из самой
ссылки. В дальнейшем возможно расширение при помощи некоего DSL, где
будут перечислены атрибуты.

Если будут какие-либо специфические формы, с выбором опций --- то
предпогается, что они просто будут добавлять некие термы в эту строку.

На верхнем уровне отображется базовая информация для ссылки: её
текстовое представление (обычно публичный ключ в base58), её тип.

Возможно, некое описание. Например, название репозитория и список
хэштегов.

Предполагается оторбражение ссылок в порядке некоего веса, который
вычисляется (TBD), возможно, формула для вычисление веса так или
иначе определяется пользователем, например, возможностью
редактирования весовых коэффициентов.

Например, факторами могут быть время обновления и отношение к
пользователю, которое может вычисляться исходя из встречаемости
его ключей в данных ссылки (как пример).

Данное требование предполагает наличие обязательных и дополнительных
полей у отображаемой ссылки.


\subsection{Отображение детализации ссылки}

Понятно, что ссылок может быть произвольное количество и hbs2-browser
не в состоянии знать их все, а тем более, осуществлять какую-то работу
с ними. У нас не стоит цели разработать и запустить универсальную CMS.

Мы не сможем встроить функции работы, например, с проектами в git в
сам браузер, и вероятно, это было бы слишком.

hbs2-browser может предоставить некоторый каркас отображения
метаинформации; возможно несколько уровней. И предоставить возможность
перенаправления на приложение, которое умеет работать со ссылкой
(данными) такого типа.

Рассмотрим примеры.

\paragraph{git} Мы бы хотели видеть: название и описание репозитория,
список авторов, README если есть, список бранчей и тегов.

Еще бы мы хотели видеть структуру каталогов, и в переспективе ---
просматривать каждый файл, как в онлайн-редакторе, так и raw виде.

Однако, непонятно, как это сделать. Проекты могут иметь огромные
размеры, как по количеству файлов, так и количеству коммитов.

Если всё это делать метаданными, то размер метаданных сравняется
или превысит размер изначальных данных, которые тоже могут
иметь миллионы записей и гигабайты/десятки гигабайт размеров
в предельных случаях (монорепозитории).

Распаковка объектов на лету тоже малоприменима --- git~object~packs
могут быть огромными, их может быть много, без полной распаковки
объект не извлечь.

Вероятно, на первом этапе стоит ограничиться списком ссылок и
детализацией информации ссылки, например, нескольких уровней -- L1,
L2. L2 подразумевает более подробную информацию о какой-то сущности
ссылки, поэтому параметризуется этой сущностью.

\paragraph{Пример:}

\begin{verbatim}
  L1:репозиторий
      -> L2:список автров
        ->  L3:автор
\end{verbatim}

С другой стороны, можно представить и таким образом:

\begin{verbatim}
  L1:репозиторий
      -> L2:список авторов
      -> L2:автор
\end{verbatim}


Видно, что задача очень хорошо бы ложилась на XML/XSLT, если бы у нас
была подобная опция.  К сожалению, в современном мире такой опции нет
и нам придётся изобретать некую замену, которая будет делать тоже
самое, но не так.


Таким образом, нам необходим способ преобразования из модели
<<фактов>> в отображаемый формат (html).

Мы не хотим, что бы этот способ был привязан к какому-то конкретному
языку программирования.

Мы не хотим, по возможности, встраивать эти преобразования в
\term{hbs2-browser}{hbs2-browser}.


Рассмотрим возможные варианты задания преобразований:

\subsubsection{SQL+JSON}

Пользователь задаёт в конфигурации SQL стейтмент, порождающий JSON +
шаблон, который преобразует JSON в формат для отображения (html/htmx).

Достаточно просто, доступный многим стек, возможны сложности с
выполнением отображения в случае, если одного SQL запроса
недостаточно, фиксируем СУБД (скорее всего, это будет sqlite, но это
деталь реализации, которую не хотелось бы раскрывать), сколько-нибудь
сложную логику писать в СУБД достаточно проблематично и способ зависит
от БД. Отсутствие нормальной типизации. Слабые возможности абстракции.


\subsubsection{Собственный EDSL}

Требуется значительное время для разработки, необходима разработка
средств разработки и отладки, высокий порог входа, возможное
недовольство пользователей.


\subsubsection{Биндинги в скриптовые ЯП + хост}

Достаточно затратное встраивание, вопрос, какие именно ЯП выбрать из
большого списка, необходимость принять множество решений при
отсутствии достаточного количества объективных факторов для их оценки
(какой язык <<лучше>>, какой <<хуже>> и множество еще)

\subsubsection{Внешний процесс + некий IPC}

К недостаткам относятся: необходимость в управлении этим процессом и
его артефактами (сокеты, named pipes).


Тем не менее, данный способ видится наиболее универсальным и простым
относительно прочих.

Способ в каком-то роде давно проверенный и доказанный: и cgi и fastcgi
работают десятилетия уже, подход масштабируется.

Внешним процессом может быть как некий сервер/сервант, так и
запускаемый нашим процессом внешний процесс, обеспечивающий
коммуникацию через pipe.

При реализации Messaging через пайпы мы получаем такой же абсолютно
RPC+Notifications, как во всех прочих частях системы: UDP, TCP, Unix
sockets.

Протокол может быть и бинарным и текстовым. Текстовый протокол может
видеться, примерно похожим на HTTP:  <<запросом>> является подобный
HTTP заголовок, далее пустая строка <<\texttt{CR LF CR LF}>>, далее
тело ответа, например, в JSON.

Заголовки могут быть урезанным набором заголовков HTTP.

При таком подходе мы можем интегрировать процессы, написанные на
других языках, они получают достаточно простой текстовый интерфейс,
при условии, что у них нет удобной реализации CBOR.

Начать же мы можем с того, что просто реализуем \texttt{Messaging} c
фреймингом, аналогичный TCP/ByPass --- но для pipes.

Этот протокол может быть и синхронным и асинхронным, вероятно, лучше
сразу же делать его асинхронным --- т.е потоки запросов и ответов
являются независимыми, а на какой конкретно запрос поступает ответ ---
зависит от специального поля в заголовке \texttt{REQID}.

При асинхронном подходе нам не обязательно балансировать нагрузку
внутри нашего хост-приложения --- балансировать может сам запущенный
процесс.

Почему нужно делать именно так: fork+RPC через pipes.

\begin{enumerate}
  \item Имея механизм RPC через потоки ввода--вывода мы можем этот же
  механизм задействовать для named~pipes, то есть, для взаимодействия
  с внешним процессом, которым мы не управляем.
  \item Мы можем управлять нужным процессом и запускать его
  самостоятельно, не полагаясь на всякие системные вещи, типа systemd
  и внешних конфигурационных скриптов, снижая количество внешних
  факторов, влияющих на функционирование системы.
  \item Мы можем балансировать нагрузку, запуская нужное нам
  количество процессов и распределяя нагрузку между ними, если они
  имеют свойство блокироваться.
\end{enumerate}

Почему бинарный протокол в первую очередь:

\begin{enumerate}
  \item Текстовый можно сделать позднее, для этого нужно просто
  подменить encode/decode в определении протокола.
  \item Это самое простое по реализации решение в данный момент, и
  отработанное на примере других протоколов/других транспортов.
  \item У нас всё уже для этого есть, и с примерами для других видов
  транспорта. Протокол для pipes будет почти полностью аналогичен
  протоколу для Unix sockets.
  \item Автор является и основным разработчиком системы, маловероятно,
  что на текущем этапе появятся какие-то другие разработчики, которые
  будут заинтересованы в разработке на других ЯП, кроме Haskell, а раз
  так, то все просто могут взять библиотеку и писать эти модули на
  Haskell.
\end{enumerate}

Почему асинхронный протокол:

Потому, что синхронный --- его частный случай, как если бы асинхронный
процесс просто затыкался после одного запроса. Это всё равно та
ситуация, которую надо уметь обрабатывать. Так что сделав асинхронную
обработку --- мы получим синхронную бесплатно. Механизмы ServiceProto
уже умеют делать синхронные вызовы для асинхронных протоколов.






