DIY: Как мы делали «живое» расписание для Codefest X

В конце марта в Новосибирске отгремел юбилейный 10-ый CodeFest. Как и, наверное, любая конференция, CodeFestX оставил участникам кучу разных впечатлений от «ноги моей тут больше не будет» до «как купить пожизненную подписку?». То, как это было я описывать не буду, отзывы уже есть и, думаю, еще появятся. Хочу поделиться историей того, как мы запустили альтернативную версию для расписания Codefest (смотреть лучше с мобилки): от идеи до получившегося результата.

a9i-frbjx1pwd_-idvj21kuwahe.jpeg

Идея


Я посещаю Codefest начиная с 2010 года, и в этом году была моя 9-ая конференция. Для меня Codefest — это традиция, и в этот раз захотелось сделать что-нибудь полезное. До начала мероприятия, читая чат конференции, я понял, что расписание — это то, что точно можно улучшить. Codefest — насыщенное мероприятие, из которого всем хотелось бы выжать максимум, поэтому я решил помочь с построением альтернативного настраиваемого расписания.

Цели были намечены следующие:

  • Для посетителей — дать возможность получить больше актуальной информации о происходящих событиях и сформировать свою ленту интересов. Плюс у всех посетителей конференции была возможность прийти на наш стенд и запилить любую недостающую фичу или пофиксить баг;
  • Для Codefest — это дополнительный канал распространения «народной» программы;
  • Для нас как компании — это, конечно же, дополнительный плюсик в Employer-бренд.

rxs9pzzpvpsnzfsdanwyrbo5alw.jpeg

Концепция «прокаченного» расписания зашла организаторам Codefest. Я поделился идеей в Wrike и быстро нашел единомышленников, готовых подключиться. Начали с исследования, посмотрели на сайты конференций и мобильные приложения. В общем, запустили обычный продуктовый процесс в Wrike.

В результате проработки бэклога определились, что необходимый функционал нужен такой:

  • Основное расписание конференции с возможностью фильтрации докладов и поиска;
  • Избранное и нотификации о приближении избранных событий;
  • Народная программа, с тем же функционалом, что и основная, а также возможность для партнеров и активистов добавлять события в эту программу.


Были задачи с приоритетом пониже:

  • Обсуждения по докладу, чтобы авторизованные пользователи могли обмениваться мнениями и дискутировать;
  • Лайки и народный рейтинг докладов;
  • Карта, т.к. CodeFest большой, и навигация очень важна.


Еще были задачи с третьим приоритетом, где у нас пока зарыта куча космических кораблей, но я верю, что их время придет.

Реализация


В качестве стека для проекта решили взять то, что используем в разработке нашего продукта, чтобы дать возможность посмотреть, как строится frontend в Wrike. Мы пишем на Dart (и уже рассказывали почему: здесь и здесь) и ПОКА для больших web-проектов, вроде нашего, есть только Angular (вот 5 минут вдохновения от bunopus). Репозиторий нашего проекта можно найти тут github.com/wrike/codefestx.

В нашем приложении к Angular мы добавили Redux. Для Dart есть несколько имплементаций: мы взяли Redux.dart и Redux Epics для эффектов. У нас в проекте относящийся к Redux код находится тут github.com/wrike/codefestx/tree/master/lib/src/redux.

Для работы с неизменяемыми состояниями (immutable state) мы взяли пакеты built_value и built_collection, которые хорошо упрощают работу. Например, мы создаем класс для state нашего приложения — CodefestState, а пакеты генерируют билдер.
Для связи Angular и Redux используется нехитрый прием (в основном компоненте — github.com/wrike/codefestx/blob/master/lib/app_component.dart):


И их мы связываем вместе через стандартный дартовый Stream:

_dispatcher.onAction.listen((action) => _store.dispatch(action)),
_store.onChange.listen((_) => _zone.run(_cdr.markForCheck)),

То есть, при создании в диспетчере действия (все они находятся тут), оно попадает в хранилище Redux. Идет его обработка и меняется состояние, что вызывает цикл ангуляровского Change Detection.
Для отправки уведомлений сделали 2 механизма: для уведомлений о наступлении событий, т.к. это важно, интегрировались с PushWoosh и получили системный push (к сожалению без поддержки браузеров на iOS). Для менее критичных событий, например, выхода новой версии, подняли сокет, а на клиенте использовали socket_io_client.

lulmlhwogwbghjqewm8y6onvxec.gif

В целом, структура приложения несложная и, на мой взгляд, понятная. Если есть вопросы, то можем конкретные решения обсудить в комментариях или на github.

Инфраструктура


В современном мире, чтобы выложить JS файлик для всеобщего пользования, без k8s не обойтись. А если серьезно, то одна из возможностей нашего сервиса — это его доработка прямо на самой конференции (чем воспользовалось несколько Dartизан среди посетителей и нет, они не из Wrike:)).

1nb0xbs7ur95vrppmx1i0gkd55i.jpeg

Поэтому решили сделать честный CI. Поглядели на те возможности интеграции, которые есть у GitHub, и нашли там Google Cloud Build: раз уж используем продукты Google, то не сходить же с этой дорожки. Интеграция работает так: любой коммит в репозиторий вызывает сборку cloudbuild.yaml. Мы пошли по пути, что собираем Docker контейнер с готовым приложением (благо шаблон для дарта есть — hub.docker.com/r/google/dart), а затем запускаем его в k8s, чтобы была возможность откатывать релизы, масштабироваться и предусматривать прочие гипотетические ситуации. Из того, чего не хватило из коробки — это возможности делать разное поведение в зависимости от ветки, куда делаем коммит, то есть, чтобы для master сборка проходила и развертывалась в бой, а для остальных веток, выполнялись минимальные шаги, без участия k8s. Есть активное обсуждение этой темы тут, и мы воспользовались решением из этой дискуссии. CI отработал на отлично и ни разу не подвел.

Ложка дёгтя


Помимо наших успехов, конечно же, есть и то, что можно было сделать по-другому. Например, не заставлять людей авторизовываться при голосовании за доклады — некоторые это не любят (тем более в краткосрочных сервисах). В итоге, мы получили не очень много «лайков» за доклады, но, тем не менее, поздравили спикеров-чемпионов.

xe0tq4-g1dpk5w764k2kkp7rgvo.jpeg

Еще мы в кураже web-разработки забыли о жестких ограничениях iOS, и что там нет возможности делать push для web. Оказалось, что почти половина пользователей нашего сервиса были с iPhone. Им мы, к сожалению, не смогли послать уведомление.
И что еще расстроило команду, как я уже упоминал, — не всё задуманное успели сделать. Часть функционала выкатывали прямо на конференции, а часть еще живет в backlog.

Результаты


Спасибо организаторам, что ссылка на расписание была добавлена в памятку участника конференции. Во время конференции сервисом воспользовалось более 1100 пользователей. К основной программе из ~120 событий, мы добавили еще ~50 «народных». Примерно 75% сессий пришлось на мобильные девайсы, мы отправили более 500 push-уведомлений, выпустили 3 релиза за время самой конференции, получили кучу удовольствия от процесса и результата.

ax7h6jbwkhnsve1quyod0g82e6w.jpeg

Это был классный опыт, а мы продолжим развивать проект, как минимум для внутренних событий и конференций Wrike. Если вы были на Codefest и пользовались нашим расписанием, будем рады вашим отзывам в комментариях.

© Habrahabr.ru