Front Web Framework: часть 4

Запилил TODO пример с использованием servant, servant-auth-cookie, wai-websockets. Ниже краткий отчёт о ходе реализации.

  • В Yesod MonadHandler добавляет к каждому запросу контекст сессии, к которому в любой момент времени можно получить доступ.
  • В куках в каждую сессию можно положить произвольную мапу, и работать с ней, как из хэндлера, так и из вебсокета.
  • В Servant такого счастья нет, надо заворачивать маршруты в куки с двух сторон, добавляя ручную обработку заголовков запроса и ответа. 
  • В пакете servant-auth нет поддержки шифрования кук, не очень безопасно получается.
  • В servant-auth-cookie (альтернатива) можно из API пакета собирать своё уютненькое шифрование с ротирующимися ключами. Для себя взял простой пример. Забавно, к пакету приложили руки мои знакомые Stack Builders из Эквадора и @mrkkrp, чьи пакеты я успешно юзал в прошлом. Пользуясь случаем, передаю привет и респект.
  • (Хотя zip он когда-то давно патчить отказался, чтобы обеспечить поддержку распаковки архива, созданного 7-Zip, как не RFC-compliant archive. Впрочем, я не в обиде).
  • servant-websockets оказался нежизнеспособным в плане анализа прилетающего реквеста, а точнее — его заголовков. Последовал совету @qnikst, взял wai-websockets и не пожалел! Респект!

Пока всё это делал, нашёл способ не завозить в Fay классы типов. 

Read more...Collapse )

Ещё одна интеграция

Опыт интеграций и миграций не проходит бесследно.

Запилена интеграция с ресурсом с посещаемостью 60K в день. Поставка аналитики туда работает в штатном режиме. А нам обратно — трафик. 

Простора для оптимизаций там масса. Например, выпилить d3 и делать SVG на сервере, а можно вообще cгенерировать и отдавать статику. Yesod должен выдержать, когда на него свалится всего 1 rps.

Это локальный успех. Даже если 0.1% будет переходить к нам, это +120 посетителей в день. Скоро будет видно. Пуск намечен на воскресенье.

Со следующей недели возобновляю разработку Front.

Front Web Framework: часть 3

28 февраля я в дичайшем угаре выступил на конференции #fprog_spb. В последний момент собрал пример для презентации, но демку не успел сделать (а зря). Слайды на коленке намутил из скриншотов. Невротик — он невротик и есть. Речь сквозила словами-паразитами, ссутулился до неузнаваемости, пережил этот вечер. Первый блин всегда комом, чего уж там.


Разгрёб фоновые задачи, начал лечение, остановил лечение, переболел. И наконец, допилил пример, поняв, что не понимаю, где рамки между клиентом и сервером, как выглядит абстракция, которую следует выделить для front.

Поэтому перехожу ко второй размерности фреймворка (из трёх задуманных пока), логичному решению, на мой взгляд: интеграции с серверными фреймворками. К имеющемуся Yesod добавляю Servant и иду далее по списку, чтобы отделить по крайней мере с одной стороны front от других.

Поскольку нужно, чтобы в любой момент времени примеры работали, решение обрастает вынужденными костылями.

Успех неизбежен.

Front Web Framework: часть 2

Прошло полтора месяца с момента прошлого поста. За это время успел зарелизить «мини-ЖЖ» в админке сайта (вторая страница), выпилить ряд костылей и добавить новых, в связи с чем открылись следующие фичи, да и вообще, вот, что сделано:

  • Разные Routes могут иметь доступ к одному State.
  • Автоматический вывод как клиентских событий, так и DOM из одного дерева Markup.
  • Поддержка небольших бинарных данных. Небольших, т.к. через base64 на клиенте. Вынужденный хак, т.к. ByteString ещё в Fay добрые люди не завезли.
  • Backdoor в мир JS. Не хочу, но оставляю незакрытой дверь на клиенте. Например, редактор текста использован внешний.
  • домен с пафосным названием haskell-front.org принадлежит мне.
  • фреймворк назван front.

К версии 0.0.1.0 пакет следует сопроводить туториалом и надо открыть роадмап.

Планов уйма, идей много. Выписываю в org-mode, пока в виде свалки.


Front Web Framework: часть 1

В хаскелле всему нужно обязательно две библиотеки. Второй библиотекой наряду с miso я и занимаюсь.

  • Нашёл подход, с которым избавился от JS!!!
  • Опубликовал первую библиотеку (пока сырую) на hackage: fay-websockets (бинарник ещё не работает, тексты ходят).
  • Стал мейнтейнером yesod-fay, Снойман делегировал.
  • Стал мейнтейнером fay и всех сопутствующих, Адам Бергмарк делегировал.
  • Зафиксил оба два пакета, чтобы работали со стэком. Надо в апстрим выплюнуть изменения.
  • Взял последнюю страницу самопальной недо-CRM и переписал её на новом подходе, используя как метамодельку, так и прорабатывая фреймворк по ходу.
  • Двусторонний обмен сообщениями между клиентом и сервером — это очень и очень хорошо.
  • Shared Types — это здорово. В нём вся соль.
  • Server State. Она будет декларироваться пользователем.
  • View. Рендерится моделька посредством blaze-html (MarkupM).
  • Events. Ивенты генерятся сервером и проксируются на клиент. 
  • На клиенте тоненький рантайм (60 строк кода), умеющий как в рендеринг, так и в регистрацию ивентов.
  • (Де)сериализация данных в JSON от феечки. Fay API позволяет гонять данные прекрасно.

На очереди auto deriving, бинарный формат данных, вторая страница и многие другие приключения... 

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

Tags: , , , ,

Метамоделирование: часть 2

Дописал клиентскую часть и оглянулся. Очень тяжелая отладка. Был бы MVC framework, как в PureScript, — было бы легче. Но тут он добавляет лишних телодвижений. Зачем, если есть модель на сервере. Хотел было уже взяться прикручивать N2O, как тут меня осенило.

  • Типы можно шарить без выпендрёжа между GHC (сервером) и Fay (клиентом).
  • Декодер уже заложен в самом Fay (Fay.Convert): конструкторы типов вместе с данными замечательно раскладываются в JSON (в соответствующие слоты). Подсмотрел даже у Сноймана пример реализации!
  • Запилил пакет для вебсокетов на Fay (опубликую на Hackage, когда моя страничка заработает).
  • Затащил поддержку различных протоколов.
  • Переписываю рендеринг на сервере, хочу посмотреть, что выйдет в итоге.

Получается эдакий FRP на коленке. Вообще, я очень доволен тем, что вырисовывается. Открытым вопросом пока является проброс новых событий для новых элементов страницы, которым ещё предстоит появиться. Либо дернуть на стороне Fay, либо прямо JS на сервере сгенерировать. Там видно будет. Пока не хочу забивать этим голову.

Метамоделирование: часть 1

Число таблиц в базе данных стало зашкаливать. Было принято жёсткое решение — не позволять их числу расти. И тут приходят на помощь метамодели. Есть всякие. 

  • Есть метаописание SOA с генератором запросов. В таком случае в каком-нибудь Oracle используют пакет dbms_sql, а в таблицах лежат нарезанными куски запросов или запросы с макросами.
  • Есть графы и гиперграфы, вырождающиеся в нечто подобное тому, что творится в Facebook.
  • Есть иерархические метамодельки, которые на первый взгляд дружат с ООП, но на деле порождают ад, когда попытаешься натянуть на них подсистему с Workflow внутри. 
  • И ещё что-то, чего я не видел, конечно.

Как водится, я в сторонке стоял по большей части, когда другие метамоделировали! Но некоторые вещи всё же умудрился пощупать вплотную. 

Взял иерархическую метамодельку за основу и решил натянуть её на Haskell с его интересными ADT. СУБД в проекте — PostgreSQL. Да, с текущими драйверами постгреса в хаскеле пока дела обстоят туговато. Все они завязаны на libpq, в недрах которого синхронно гоняются строки. 

Нативных драйверов готовых нет, есть два экспериментальных: 

  • Hasql >= 0.20.
  • postgresql-wire (нет на Hackage).

А они уже очень скоро понадобятся. Потому как уже очень скоро я упрусь в тормоза.

Завёл пока «строку», «число» и «время» в кач-ве типов атрибутов. Завёл парочку объектных типов. Завёл рута-родителя. И начал собирать грабельки.

Read more...Collapse )

10 KLoC: achievement unlocked

Хобби-проект, стартовавший как сайтик-эксперимент, постепенно превратился в распределенную систему. Состав примерно такой...

Окружения 

  • лаптопа (DEV);
  • двух серверов (STAGING, PRODUCTION).

Компоненты

  • собственно, application server;
  • бот, работающий в режиме интеграции (см. сериалы «Web Scraper», «Парсер»);
  • телеграм-бот, про который я расскажу чуть ниже;
  • билд-деплой-тула, умеющая в матрицу «компонент» × «окружений» и билдить, чистить, деплоить, перезапускать.

Телеграм-бот

Бот работает по двум направлениям: 

  • шлёт админам ресурса баг-репорты (5XX коды, + некоторые критические уведомления (самодельная наколеночная Capacity management system: alarms, thresholds, metrics);
  • шлёт менеджерам уведомления о человеческих заявках.

Особенность бота в том, что в него ещё воткнут сервер с самописным API, удовлетворяющим исключительно мои требования — уметь принимать сообщения с разных окружений и доставлять разным пользовательским группам и всё с этим связанное. Так решена проблема с блокировкой телеграма, нет нужды слать запросы напрямую. 

Благодаря Servant, API прекрасно шарится без лишних движений между сайтом (клиент) и ботом (сервер).

А 10 KLoC — блин, это всё трехэтажные SQL, и hamlet (html) шаблоны, опердень ведь должна быть динамической, не так ли?

Web-scraper: часть 8 и последняя

Забыл сказать, что описанное в прошлом посте, реализовано и просто работает. 

  • Локальный клиент по расписанию собирает дельту и шлёт на сервер. 
  • Сервер вычитывает очередную пачку данных и кладёт их в табличку базы. 
  • Локальный клиент умеет возобновлять свою работу с места падения/остановки, хотя этим мало кого сейчас удивишь.
  • С фантомом on-demand интеграция работала 8 секунд, с servant-client — 2 секунды, сейчас данные достаются из кэша за менее, чем секунду. И это успех.
  • Обновил весь проект до GHC 8.4.3. Побочный эффект апгрейда: Снойман сделал меня мейнтейнером пакета yesod-fay, которым помимо меня пользуется ещё полтора человека. И это тоже успех, хоть и сомнительный.

Надо сформировать новый сериал. О работе пока не буду писать.

Web Scraper 7 + Job change: servant-client in production

Yesod + Servant два в одном. Меня немного мутит от факта стыковки их вместе, но пока пусть комбайн живёт. 

  • Целую неделю выверял сцепку по данным и переключение интерфейса, датафиксы отлаживал на тестовом стенде.  
  • Вынес весь сервант в отдельный пакет, переиспользовал его в offline туле для опроса таргетов, чтобы уменьшить и трафик, и нагрузку на целевой ресурс.

Теперь шаг 2 — отвязать интеграцию от сервера и добить offline tool для работы в режиме джобы, и начать собирать «статистику» на регулярной основе. Путь долгий, но надо двигаться дальше.

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

Теперь работаю в «коворкинге». На место офиса пришёл офис поменьше с чужими людьми, сдающими посадочное место в аренду. Условия спартанские: стол, стул, розетка. Отдельно — чайник, чашка. 

Из неприятного: пока что люди 50/50 ок и не ок на уровне интуиции. Вечером мужик из другой комнаты на кого-то орал. Другой мужик докопался до меня среди дня с позиции заискивания передо мной. Женщина в комнате со мной ОЧЕНЬ громко говорила по телефону один раз. Извинялась потом. Что ж, если так — надо обозначать границы дозволенного и пресекать вторжения. Доверия нет таким людям, поэтому сумка с лаптопом идёт со мной на обед за пределы сего «коворкинга». Месяц уплачен. В сентябре попробую другое место.