-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Дрезина -- это такой велосипед, который ездит по рельсам. Нуфф сказал.
-
Описание внутренностей совместной работы HTML-форм и ORM-объектов
-
Описание некоторых концепций, касающихся внутреннего устройства дрезины
На момент активной разработки смешаны кое-какие вещи. Правильно должно быть так:
- директория
tpl
-- ставится вместе с дрезиной куда-то - директория
proj
-- пользовательский код, шаблоны, конфигурация - директория
proj-build
-- место, куда генерируется и где впоследствии компилируется код; вероятно должно быть поддиректориейproj
, например,proj/.dresina-build
Пока всё в одном репозитории, так гораздо проще делать первые шаги. И пока оставим как есть.
Следовательно, для инсталляции необходимо склонировать репозиторий и играться в нём.
Но дрезина требует много внешних зависимостей (мы же не велосипедисты, чтобы всё с нуля рисовать). Для простой их установки можно использовать OPAM, с его помощью можно добавить opam-репозиторий с нашими зависимостями:
$ opam remote add -k hg https://bitbucket.org/gds/repo-dresina
обновить пакеты opam'а:
$ opam update
и установить то, что нужно (остальное подтянется по зависимостям):
$ opam install amall ecaml ocamldep-sorter
После этого можно собирать дрезину.
-
Подумать, как быть с роутами и контролерами. Что нужно:
- Комар заблевал от кодогенерации и грозится придумать роуты с биндами.
- Сделать так, чтобы не-блевотное легко подключалось в нужное место обработки роутов.
- Обработка параметров запроса ("?k=v") в роутах (брать
Uri.parse_params
) - Обработка не только get-роутов; там же: на основании заголовков определять, что дают в теле post: форму или заливку файлов.
-
Продумать, как будут дела с окружением (dev/prod).
- Для dev-окружения -- хрень, которая будет проверять, не изменились ли исходники, при изменении запускать ребилдилку, прибивать старый процесс и запускать новый, и только потом передавать ему запрос.
- В prod-окружении не отдавать статику -- считаем, мы за nginx. (но сделать это опциональным -- вдруг наивный смелец решится выставить дрезину голой жопой в интернеты.)
-
Придумать что-нибудь революционное для работы с формами.
- Для этого, наверное, описать тут, чем плохо спиздить формы с тех же рельсов.
-
Параметры форм, куки и заливка файлов (посмотреть в amall, iterateees, либо в коде с прошлого рабства). Для декодирования ебанутого js-escaped utf16 есть код в iteratees точно. multipart для заливки файлов -- iteratees_http.ml / it_multipart.
-
БД
- собственно соединение с БД
- почесать dbi.pg на предмет человеческого dbi-подобного интерфейса; сделать интерфейс мономорфным относительно вида БД (пусть через coercions)
- научиться применять простые миграции и следить за текущей схемой БД
- (в мечтах любителя колупаться в camlp4) Заставить PGOcaml выдавать объекты или рекорды.
-
Шаблоны html. Брать ecaml. Текущие вопросы:
- описать и отладить соображения по поводу @x.y.z в шаблонах, таких, чтобы @x.y.z заменялось на реальные, заранее полученные в контроллере данные из базы данных, согласно описаниям моделей и ручным данным (для хитрых случаев нужно иметь возможность вносить руками данные, которые будут доступны в шаблонах).
-
Кеширование на сервере.
- брать последнюю дату создания/изменения объектов, протаскивать её везде,
сделать комбинатор типа
respond_cached сущности ответ
, который по сущностям будет определять, нужно ли отдавать ответ? Тут именно с технической стороны надо сделать пиздато, так как концепции ясны.
- брать последнюю дату создания/изменения объектов, протаскивать её везде,
сделать комбинатор типа
-
Попробовать присунуть ADT в роуты и в БД. Насчёт БД будет сложно, а с роутами вроде и просто, и заебись.
-
Мелочёвка:
- Скопипастить себе
Buffer
и сделать там вывод содержимого буфера через lwt, чтобы не копировать изBuffer.t
в отдельную строку - К предыдущему: из буфера копируется в строку, из строки при write копируется в ещё один, на этот раз сишный буфер, и оттуда уже write() пишет. Надо делать на bigarray (выделять почанково) и использовать хуйню (которая в сишечке io_vec штоле), которая умеет брать кучу (char* ofs, int len) и одним системным вызовом срать в сокет из памяти. Профит: минус одно копирование данных. Bigarray -- так как можно сделать его "C-managed" без перемещений, вызываемых мусорщиком.
- Всё, выполняющееся от роутов, будет завёрнуто в IO-монаду. Поэтому для
обработки тел запросов итератами нужно будет написать функцию вида
run_iteratee : iteratee char 'a -> ('a -> IO.m 'b) -> IO.m 'b
, которая будет брать итерат и продолжение, кидать заданное исключение, выходить из IO-монады, обрабатывать итератом тело запроса, передавать результат в продолжение, и дальше выполняться в рамках IO. - ocamldep можно запускать только на изменённых файлах, но подумать ещё. Как вариант -- смотреть, какие файлы изменены, запускать ocamldep только для этих файлов, а потом руками сливать старый .depend и вывод ocamldep для новых файлов.
- Поставить таймаут на вызов действия контроллера, сделать конфигурабельным.
- Завершением воркеров, отслеживанием таймаутов, прибиением, обновлением воркеров на новый бинарник будет заниматься аналог юникорна. Для обновлений будет два разных сокета -- старые и новые соединения. При обновлении юникорн должен отправлять новые соединения на новый бинарник, ждать отсыхания соединений со старого бинарника и прибивать старые процессы. В воркерах не нужно дополнительной логики про завершение. А таймауты в качестве простой оптимизации -- в воркерах не лишне. На случай, если тред чисто lwt и пригоден к прибиванию.
- Посмотреть, что можно сделать с main_{pre,post}, чтобы не склеивать его, а положиться на модульную систему.
- ecaml: сливать фиксированные строки шаблона в один большой Buffer.add_string.
- Скопипастить себе