- PVSM.RU - https://www.pvsm.ru -

Clojure Cup — опыт участия в хакатоне по написанию веб-приложения на Clojure

Clojure Cup — опыт участия в хакатоне по написанию веб приложения на Clojure

На этих выходных прошёл ClojureCup — 48 часовый хакатон на Clojure. Это будет относительно длинный пост про то, как он проходил в нашей команде, с техническими деталями и прочим. А в конце поста, куда уж без этого, расскажем совсем немного о нашем проекте.

Рабочее окружение

В участии в хакатоне есть два разных «режима»: участие ради удовольствия и ради победы. В первом случае мы лениво кодим что-то прикольное двое суток; во втором всё немного по-другому, с хардкором и ранним началом подготовки. Мы выбрали второй вариант.
В команде нас было четверо — двое, включая меня и si14 [1], находятся в Петербурге, один — в Тюмени (zloy_alu [2]), еще один — в Мюнхене. Но никаких проблем в коммуникации мы не испытывали — помогала более-менее успешная изоляция задач, отличный сервис Trello [3] и просто божественный FlowDock [4]. Последний, на мой взгляд представляет собой идеал сервиса для внутрикомандного взаимодействия. Судите сами — здесь есть и чат, и обмен файлами, и отдельные ветки обсуждений, и нотификации о разного рода событиях (деплой, push в репозиторий, новые задачи в trello, упоминание в твиттере). Выглядит это все примерно так:

Clojure Cup — опыт участия в хакатоне по написанию веб приложения на Clojure

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

  • проверили выбранные библиотеки и структуру приложения в целом (подробнее см. ниже про Clony);
  • проверили интеграцию со сторонними сервисами вроде NewRelic;
  • завели блог и Twitter;
  • научились быстро и удобно деплоить (Makefile'ы и Ansible);
  • подготовили документацию к JSON API между сервером и web app'ом, что позволило нам писать эти куски более-менее независимо;
  • подготовили эскизы интерфейса на бумаге;
  • купили домен и выписали SSL-сертификат;
  • научились настраивать nginx для нормальной работы с вебсокетами и статическими ресурсами;
  • подготовили контакты пула бета-тестеров (тут вышел некоторый фейл — мы отстали от графика и сделали рассылку только в 11 Москвы, поэтому успели получить только один отзыв до конца хакатона).

Технические подробности

А теперь детали о том, что может оказаться полезным для веб-разработчиков на Clojure.

Очень полезным оказался опыт создания небольшого приложения Clony [5]. Это крайне простая штука на Clojure с использованием http-kit [6] (http-сервер и клиент для Clojure) и Compojure [7] (роутер), общающееся со своим фронтендом вебсокетами. В нём используется Stuart Sierra's workflow [8], благодаря чему разработка становится ощутимо приятнее: мы целиком перезапускали всё наше приложение (или его куски) из nrepl за доли секунды. В ходе хакатона мы сделали несколько улучшений, которые ждут своего backport'а в Clony.

День первый

Мы заранее знали, что будем разворачиваться на виртуальную машину, поэтому научилсь пользоваться Ansible [9]. Благодаря ему мы были онлайн спустя 4 часа с начала соревнований — с полностью развёрнутой production-конфигурацией и тестовым приложением. Это произошло бы раньше, если бы не проблемы с DigitalOcean [10], предоставлявшим хостинг [11] для участников (они забанили наш аккаунт из-за подозрения на fraud). Также у нас были локальные виртуалки (Vagrant [12] — супер!) с полностью идентичной конфигурацией, но в итоге все забили на них и деплоили сразу в продакшн. Произошло это в том числе потому, что некоторые вещи пришлось менять прямо на лету на сервере руками — начиная от конфигурации MariaDB (чёрт подери эти ANSI_QUOTES! Надо было сразу брать Postgres) и заканчивая тем, что мы забыли писать логи на диск. Плюс мы сделали достаточно полную интеграцию с NewRelic [13]. Не могу сказать, что он нас критически выручил, но возможность легко увидеть настолько большое количество параметров — время ответа сервера, время рендеринга DOM'а клиентами, задержки сети, количество свободной памяти на сервере, статистику GC JVM — сильно успокаивала нервы. Библиотека для интеграции получилась очень небольшой и мы обязательно её выложим в open-source.

В первый день мы потратили очень много времени на попытки завести clang [14] — интеграцию Angular.js с ClojureScript. Обилие мелких неприятностей в итоге заставило отказаться от ClojureScript целиком и переключиться на голый JavaScript. ClojureScript гораздо лучше, как язык, но в условиях хакатона сражаться с собственным непониманием его тонкостей было просто некогда.

Пытаясь сделать все как можно более правильно, мы решили добавить в проект библиотеку для SQL-миграций. Интересно было обнаружить, что весьма популярная библиотека для миграций Lobos [15] не работает вовсе [16]. В результате мы потеряли около часа на поиск и разбирательство с новой; остановились на Ragtime [17].

В итоге в конце первого дня у нас была красивая главная страница и полурабочий список репозиториев (небольшое описание нашего проекта чуть ниже). В промежутке 22:00–03:00 команда разбрелась спать (к этому моменту никто не спал с 4 утра) и снова собрались мы около 8 утра в воскресенье.

День второй

В воскресенье дела пошли лучше, но и проблем было достаточно много:

  • пришлось переделать небольшой кусок OAuth-авторизации;
  • в какой-то момент нас забанил GitHub по лимиту запросов API, что было крайне неприятно, и нам пришлось количество отправляемых запросов;
  • для генерации картинок мы сначала пытались использовать что-то на чистой Java, но в итоге взяли биндинг к ImageMagick. Их есть два: один работает через sh и pipes, другой через JNI. Первый тормозит (30+мс на картинку), на завести второй так и не удалось;
  • и с медленной генерацией картинок, и с количеством запросов к GitHub нас выручил core.cache [18] — прекрасная «core» библиотека Clojure;
  • мы приняли рискованное решение взять core.async для работы с событиями на сервере. В итоге это оказалось неплохим решением: первая рабочая версия кода с его использованием родилась за полтора часа и проблем с ним практически не было, несмотря на то, что никто в команде до этого его не использовал. С помощью core.async мы сделали возможность из любого места кода удобно писать в вебсокет конкретного пользователя и сложную логику перезапуска сканирования репозиториев в случае перегрузки сервера: мы обрабатываем очередь запросов на сканирование, отбрасывая всё, что переполняет очередь, и в случае отсутствия заданий в основной очереди выбираем из базы то, что выбросили при перегрузке. Код получился очень компактным и вроде бы работает;
  • баги на клиенте, часть из которых, увы, мы не успели исправить до конца хакатона.

В целом, второй день прошёл более чем продуктивно. Мы пытались ориентироваться на первое впечатление, поэтому уделили внимание мелочам: редирект на наш собственный домен, красивый «How to Use», понятный текст на главной, приятный дизайн, плашки с «извините, у вас нет TODO в репозитории, вот форма багрепорта, если это не так». Конечно, для ускорения разработки мы использовали Bootstrap [19], но попытались сделать все максимально красиво и «недефолтно». Насколько это всё поможет нам получить лучшие оценки от судей, мы узнаем в пятницу.

Самое интересное — о чем это все?

Будет странным совсем ничего не сказать о нашем проекте.
Нам кажется, человечество ещё не придумало идеальный багтрекер. Впрочем… Зачем нам багтрекер вообще? Суть нашего проекта — убрать отдельный багтрекер из вашей жизни. И мы постарались и будем стараться дальше для того, чтобы он мог выглядеть так:

def somefun():
    # TODO: si14 [1], please fix this before release
    return true

А остальное сделаем мы — вышлем пользователю нотификацию о том, что вы создали для него задачу, отобразим ее в нашем интерфейсе, а также будем следить за вашими коммитами и сканировать код на предмет новых TODO, FIXME и NOTE. Кроме того, вы можете сгенировать красивую картинку для своего репозитория на GitHub с указанием того, сколько TODO в вашем коде и ссылкой на информацию об этом. Наш проект CodeNotes [20] пока не обладает всем желаемым функционалом (плюс там пока есть немного достаточно досадных багов, что уж скрывать), но когда голосование закончится, мы тут же продолжим улучшать его и делать из него лучший багтрекер для небольших проектов.

А пока, кстати, вы можете проголосовать за нас [21] и высказаться в комментариях о том, что вы думаете об идее, о хакатонах и в целом о веб-программировании на Clojure.

Автор: alwxndr

Источник [22]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/44803

Ссылки в тексте:

[1] si14: http://habrahabr.ru/users/si14/

[2] zloy_alu: http://habrahabr.ru/users/zloy_alu/

[3] Trello: http://trello.com

[4] FlowDock: http://flowdock.com

[5] Clony: http://github.com/si14/clony

[6] http-kit: http://http-kit.org/

[7] Compojure: https://github.com/weavejester/compojure

[8] Stuart Sierra's workflow: http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

[9] Ansible: https://github.com/ansible/ansible

[10] DigitalOcean: http://digitalocean.com

[11] хостинг: https://www.reg.ru/?rlink=reflink-717

[12] Vagrant: http://vagrantup.com

[13] NewRelic: http://newrelic.com

[14] clang: https://github.com/pangloss/clang

[15] Lobos: https://github.com/budu/lobos

[16] не работает вовсе: https://github.com/budu/lobos/issues/55

[17] Ragtime: https://github.com/weavejester/ragtime

[18] core.cache: https://github.com/clojure/core.cache

[19] Bootstrap: http://getbootstrap.com

[20] CodeNotes: http://codenotes.me

[21] проголосовать за нас: http://clojurecup.com/app.html?app=codenotes

[22] Источник: http://habrahabr.ru/post/196090/