mirror of https://github.com/voidlizard/hbs2
238 lines
14 KiB
TeX
238 lines
14 KiB
TeX
% 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
|
||
уже умеют делать синхронные вызовы для асинхронных протоколов.
|
||
|
||
|
||
|
||
|
||
|
||
|