Yesod = Haskell $ Web

в 17:19, , рубрики: haskell, heroku, Веб-разработка, метки: ,

Haskell — пока еще единственный язык программирования, в котором есть оператор «фтопку» (>>=)

Абсурдопедия

Планировал начать с описания того, как ошибаются люди, полагающие Haskell бесполезным с практической точки зрения, сферическим языком в вакууме и т.д. Но, боюсь, за меня все уже сделали авторы Real World Haskell. Была идея рассказать о том, насколько красив и могуч этот язык программирования — но подвел тяжелый слог и неумение придумать захватывающий сюжет с неожиданной развязкой. Поэтому отброшу все лишнее и расскажу о своих злоключениях веб-разработки на Haskell.

Действующие лица

Давно хотелось попробовать Haskell для разработки в web. Во-первых — это достаточно близко к моей профессиональной деятельности, во-вторых — это дико интересно) Ну и в итоге получаем способ изучить Haskell и не заснуть за алгоритмами сортировки и поиска факториалов.

Благо, для данного замысла существует куча готовых фреймворков (см. здесь) и необходимых пакетов (впрочем, их существуют неведомые горы для всего).
В сухом остатке, я выбрал Yesod Web Framework. Хотя он достаточно распространен и обладает хорошим функционалом, признаюсь, выбор был совершен методом научного тыка и малообоснован логически.
Помимо этого, хотелось иметь возможность не только поглядеть на результаты своего труда локально, но и похвастаться перед коллегами. Поэтому было задумано опубликовать результаты на Heroku. Для этого потребуется haskell buildpack, например этот (хотя, заранее сообщу, что в моем случае заработал только он))

Yesod

Я постараюсь описать все достаточно подробно и полно — на всякий случай. Итак, для начала потребуется установить Glasgow Haskell Compiler. Любым пакетным менеджером:

emerge -av ghc

Не помешает также cabal:

emerge -av cabal
cabal update

Для того, чтобы не ломать голову над зависимостями, стоит использовать cabal-dev, который позволит устанавливать все необходимые в дальнейшем пакеты в sandbox (похоже на virtualenv).

cabal install cabal-dev

Теперь создадим заготовку для первого приложения. Собственно, за нас все сделает yesod:

yesod init

Указываем название приложения, способ хранения данных (например, в postgresql) и вуаля — получаем директорию с вполне функционирующим веб-приложением. Осталось только установить зависимости с помощью cabal-dev:

cd MyApp
cabal-dev install

Немного медитации на консольный выхлоп — и мы на шаг ближе к реализации задумки. Осталось не забыть указать конфигурацию для бд. Ее можно увидеть в файле config/postgresql.yml — и здесь уже все украдено до нас продумано за нас! В файле присутствуют 4 вида конфигураций (development, testing, staging, production) и конфигурация по умолчанию, от которой все наследуются. Осталось указать имя пользователя бд, пароль и название базы.
Теперь запустим сервер:

yesod devel --dev

Опция --dev сообщает, что необходимо использовать cabal-dev — иначе Yesod будет искать пакеты, установленные в системе.
Все, можно, затаив дыхание, открыть в браузере http://localhost:3000 и насладиться пусть достаточно простым, но уже результатом.

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

cabal-dev build / yesod build

или просто перезапустить development сервер — нужно еще и заново установить приложение

cabal-dev install

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

Heroku

Следующий эпизод будет посвящен публикации полученного веб-приложения на Heroku. Вся эта затея возможна благодаря runtime stack под названием Cedar. При использовании этого стека, поддержка различных языков и фреймворков полностью ложится на плечи buildpack'ов, которые подготавливают окружение для запуска приложения.
Heroku поддерживает несколько таких buildpacks, например, для Ruby (ну кто бы сомневался), Node.js, Python и т.д. Помимо этого списка есть знатное количество сторонних buildpacks .
Естесственно, нам нужен таковой для Haskell, который находится без особого труда в указанном выше списке. Причем находится к моему удивлению, т.к. я обнаружил это совсем недавно, а еще некоторое время назад его там не было. На тот момент это сподвигло меня на поиск по github и перебор нескольких репозиториев, среди которых в моих руках заработал этот.

Итак, создаем приложение на heroku:

heroku create my-app --stack=cedar --buildpack https://github.com/<путь к выбранному buildpack>.git

Далее надо инициализировать git репозиторий и добавить в него MyApp. Перед деплоем необходимо внести некоторые изменения, про которые легко можно забыть. Для начала, надо перенести Procfile из директории deploy в корень проекта — в этом файле содержится информация о том, как запустить проект. После стоит поправить production конфигурацию бд и сайта:

  • approot из config/settings.yml должен указывать на итоговый url приложения (для загрузки статики, например, «my-app.herokuapp.com»)
  • user, password и т.д. из config/postgresql.yml должны содержать реальные данные heroku

По поводу бд — естесственно, для начала необходимо добавить add-on Heroku Postgres. После добавления можно узнать строку подключения командой

heroku pg:info #получаем HEROKU_POSTGRESQL_URL
heroku pg:credentials HEROKU_POSTGRESQL_URL

После комита всех произведенных изменений, указываем удаленный репозиторий heroku:

heroku git:remote -a MyApp

и отправляем изменения на сервер

git push heroku master

Ждем… Перед деплоем с помощью buildpack'а будет подготовлено окружение, будут установлены все зависимости и т.д.
И вот здесь может возникнуть проблема, которая заставляет задуматься. Дело в том, что heroku устанавливает ограничение, которое может не позволить завершить деплой. В попытках выяснить, как и почему, я клонировал репозиторий buildpack'а и осмотрел его. Подопытный напрашивался на эксперименты. Чтобы иметь возможность использовать buildpack локально и, соответственно, сразу видеть результаты всех модификаций, можно воспользоваться плагином heroku push. В этом случае деплой проекта будем производить минуя git:

heroku push -b ~/mybuildpack

После внесения некоторых изменений:

-export PATH=$FIXED_HOME/ghc/bin:$FIXED_HOME/.cabal/bin$PATH
+export PATH=$FIXED_HOME/ghc/bin:$FIXED_HOME/.cabal/bin:$PATH

-cabal install -j5 --disable-library-profiling --disable-executable-profiling --disable-shared
+cabal install -j2 --disable-library-profiling --disable-executable-profiling

к моему удивлению, все заработало и деплой прошел успешно! (бурное обсуждение в комментах поощряется, т.к. я сам доконца не понял, почему это сработало)

Заключение

Yesod — интересный и конкурентноспособный фреймворк, который обладает большим набором возможностей. Любопытно посмотреть на Yesod vs Django. До этого меня останавливал только тот факт, что никто из облачных сервисов вроде GAE, OpenShift и т.д. не собираются иметь дело с Haskell. Ну а раз проблема исчерпана, то можно и даже нужно порадовать себя изучением еще одной интересной штуки. Надеюсь, я не одинок в своих порывах)
В дальнейшем постараюсь рассказать о том, как работает и устроен Yesod. Будет много Шекспира и других плюшек)

P.S.:
Пара презентаций об использовании Haskell в production
mth.io/talks/haskell-in-production
www.shimweasel.com/hs_gbu

Автор: erthalion

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js