- PVSM.RU - https://www.pvsm.ru -
В конце марта в Новосибирске отгремел юбилейный 10-ый CodeFest [1]. Как и, наверное, любая конференция, CodeFestX оставил участникам кучу разных впечатлений от «ноги моей тут больше не будет» до «как купить пожизненную подписку?». То, как это было я описывать не буду, отзывы уже есть [2] и, думаю, еще появятся. Хочу поделиться историей того, как мы запустили альтернативную версию для расписания Codefest [3] (смотреть лучше с мобилки): от идеи до получившегося результата.
Я посещаю Codefest начиная с 2010 года, и в этом году была моя 9-ая конференция. Для меня Codefest — это традиция, и в этот раз захотелось сделать что-нибудь полезное. До начала мероприятия, читая чат конференции, я понял, что расписание — это то, что точно можно улучшить. Codefest — насыщенное мероприятие, из которого всем хотелось бы выжать максимум, поэтому я решил помочь с построением альтернативного настраиваемого расписания.
Цели были намечены следующие:
Концепция «прокаченного» расписания зашла организаторам Codefest. Я поделился идеей в Wrike и быстро нашел единомышленников, готовых подключиться. Начали с исследования, посмотрели на сайты конференций и мобильные приложения. В общем, запустили обычный продуктовый процесс [4] в Wrike.
В результате проработки бэклога определились, что необходимый функционал нужен такой:
Были задачи с приоритетом пониже:
Еще были задачи с третьим приоритетом, где у нас пока зарыта куча космических кораблей, но я верю, что их время придет.
В качестве стека для проекта решили взять то, что используем в разработке нашего продукта, чтобы дать возможность посмотреть, как строится frontend в Wrike. Мы пишем на Dart [5] (и уже рассказывали почему: здесь [6] и здесь [7]) и ПОКА [8] для больших web-проектов, вроде нашего, есть только Angular (вот 5 минут вдохновения [9] от bunopus [10]). Репозиторий нашего проекта можно найти тут github.com/wrike/codefestx [11].
В нашем приложении к Angular мы добавили Redux [12]. Для Dart есть несколько имплементаций: мы взяли Redux.dart [13] и Redux Epics [14] для эффектов. У нас в проекте относящийся к Redux код находится тут github.com/wrike/codefestx/tree/master/lib/src/redux [15].
Для работы с неизменяемыми состояниями (immutable state) мы взяли пакеты built_value [16] и built_collection [17], которые хорошо упрощают работу. Например, мы создаем класс для state нашего приложения — CodefestState [18], а пакеты генерируют билдер [19].
Для связи Angular и Redux используется нехитрый прием (в основном компоненте — github.com/wrike/codefestx/blob/master/lib/app_component.dart [20]):
И их мы связываем вместе через стандартный дартовый Stream [24]:
_dispatcher.onAction.listen((action) => _store.dispatch(action)),
_store.onChange.listen((_) => _zone.run(_cdr.markForCheck)),
То есть, при создании в диспетчере действия (все они находятся тут [25]), оно попадает в хранилище Redux. Идет его обработка и меняется состояние, что вызывает цикл ангуляровского Change Detection.
Для отправки уведомлений сделали 2 механизма: для уведомлений о наступлении событий, т.к. это важно, интегрировались с PushWoosh [26] и получили системный push (к сожалению без поддержки браузеров на iOS). Для менее критичных событий, например, выхода новой версии, подняли сокет, а на клиенте использовали socket_io_client [27].
В целом, структура приложения несложная и, на мой взгляд, понятная. Если есть вопросы, то можем конкретные решения обсудить в комментариях или на github.
В современном мире, чтобы выложить JS файлик для всеобщего пользования, без k8s [28] не обойтись. А если серьезно, то одна из возможностей нашего сервиса — это его доработка прямо на самой конференции (чем воспользовалось несколько Dartизан среди посетителей и нет, они не из Wrike :)).
Поэтому решили сделать честный CI. Поглядели на те возможности интеграции, которые есть у GitHub [29], и нашли там Google Cloud Build [30]: раз уж используем продукты Google, то не сходить же с этой дорожки. Интеграция работает так: любой коммит в репозиторий вызывает сборку cloudbuild.yaml [31]. Мы пошли по пути, что собираем Docker контейнер с готовым приложением (благо шаблон для дарта есть — hub.docker.com/r/google/dart [32]), а затем запускаем его в k8s, чтобы была возможность откатывать релизы, масштабироваться и предусматривать прочие гипотетические ситуации. Из того, чего не хватило из коробки — это возможности делать разное поведение в зависимости от ветки, куда делаем коммит, то есть, чтобы для master сборка проходила и развертывалась в бой, а для остальных веток, выполнялись минимальные шаги, без участия k8s. Есть активное обсуждение этой темы тут [33], и мы воспользовались решением из этой дискуссии. CI отработал на отлично и ни разу не подвел.
Помимо наших успехов, конечно же, есть и то, что можно было сделать по-другому. Например, не заставлять людей авторизовываться при голосовании за доклады — некоторые это не любят (тем более в краткосрочных сервисах). В итоге, мы получили не очень много «лайков» за доклады, но, тем не менее, поздравили спикеров-чемпионов.
Еще мы в кураже web-разработки забыли о жестких ограничениях iOS, и что там нет возможности делать push для web [34]. Оказалось, что почти половина пользователей нашего сервиса были с iPhone. Им мы, к сожалению, не смогли послать уведомление.
И что еще расстроило команду, как я уже упоминал, — не всё задуманное успели сделать. Часть функционала выкатывали прямо на конференции, а часть еще живет в backlog.
Спасибо организаторам, что ссылка на расписание была добавлена в памятку участника конференции. Во время конференции сервисом воспользовалось более 1100 пользователей. К основной программе из ~120 событий, мы добавили еще ~50 «народных». Примерно 75% сессий пришлось на мобильные девайсы, мы отправили более 500 push-уведомлений, выпустили 3 релиза за время самой конференции, получили кучу удовольствия от процесса и результата.
Это был классный опыт, а мы продолжим развивать проект, как минимум для внутренних событий и конференций Wrike. Если вы были на Codefest и пользовались нашим расписанием, будем рады вашим отзывам в комментариях.
Автор: Demetrikl
Источник [35]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/razrabotka/315055
Ссылки в тексте:
[1] CodeFest: https://2019.codefest.ru/
[2] уже есть: https://youtu.be/N1oy7dGuSEI
[3] альтернативную версию для расписания Codefest: https://codefest.wrike.tech/welcome
[4] продуктовый процесс: https://youtu.be/aMLS3sr0diE
[5] Dart: https://www.dartlang.org/
[6] здесь: https://habr.com/ru/company/wrike/blog/330832/
[7] здесь: https://habr.com/ru/company/wrike/blog/330900/
[8] ПОКА: https://medium.com/flutter-io/hummingbird-building-flutter-for-the-web-e687c2a023a8
[9] 5 минут вдохновения: https://youtu.be/0mHspoS5Zf8
[10] bunopus: https://habr.com/ru/users/bunopus/
[11] github.com/wrike/codefestx: https://github.com/wrike/codefestx
[12] Redux: https://hackernoon.com/redux-step-by-step-a-simple-and-robust-workflow-for-real-life-apps-1fdf7df46092
[13] Redux.dart: https://pub.dartlang.org/packages/redux
[14] Redux Epics: https://pub.dartlang.org/packages/redux_epics
[15] github.com/wrike/codefestx/tree/master/lib/src/redux: https://github.com/wrike/codefestx/tree/master/lib/src/redux
[16] built_value: https://pub.dartlang.org/packages/built_value
[17] built_collection: https://pub.dartlang.org/packages/built_collection
[18] CodefestState: https://github.com/wrike/codefestx/blob/master/lib/src/redux/state/codefest_state.dart
[19] билдер: https://github.com/wrike/codefestx/blob/master/lib/src/redux/state/codefest_state.g.dart
[20] github.com/wrike/codefestx/blob/master/lib/app_component.dart: https://github.com/wrike/codefestx/blob/master/lib/app_component.dart
[21] здесь: https://webdev.dartlang.org/angular/note/effective/change-detection
[22] здесь: https://github.com/johnpryan/redux.dart/blob/master/doc/why.md
[23] github.com/wrike/codefestx/blob/master/lib/src/redux/services/dispatcher.dart: https://github.com/wrike/codefestx/blob/master/lib/src/redux/services/dispatcher.dart
[24] Stream: https://www.dartlang.org/tutorials/language/streams
[25] тут: https://github.com/wrike/codefestx/tree/master/lib/src/redux/actions
[26] PushWoosh: https://www.pushwoosh.com/
[27] socket_io_client: https://pub.dartlang.org/packages/socket_io_client
[28] k8s: https://kubernetes.io/
[29] GitHub: https://github.com/marketplace/category/continuous-integration
[30] Google Cloud Build: https://cloud.google.com/cloud-build/
[31] cloudbuild.yaml: https://github.com/wrike/codefestx/blob/master/cloudbuild.yaml
[32] hub.docker.com/r/google/dart: https://hub.docker.com/r/google/dart/
[33] тут: https://github.com/GoogleCloudPlatform/cloud-builders/issues/138
[34] нет возможности делать push для web: https://help.pushwoosh.com/hc/en-us/community/posts/360000826663-Mobil-Safari
[35] Источник: https://habr.com/ru/post/448610/?utm_campaign=448610
Нажмите здесь для печати.