?

Log in

No account? Create an account

Стой под стрелой

Поступки и мысли, о которых могу вспомнить не краснея

Previous Entry Поделиться Next Entry
Хакатончик
усы2
tonsky

Я опять упоролся ClojureCup-ом, в этот раз немного совершенно в другом составе. Делали мы ачивменты для Git:

Объяснение и карточка проекта

ВАЖНО: приложение работает, но там уже много всякого накидали, а мы к SaaS не очень готовы были — нам бы основной функционал накидать — поэтому экспериментируйте, но ничего большого просьба не добавлять. Эту версию нам нельзя трогать до понедельника, пока идет голосование, прошу отнестись с пониманием.

Прямая ссылка на приложение: http://acha.clojurecup.com

Я занимался преимущественно UI, естественно, искал повода воткнуть DataScript. И он нас сильно спас.

Во-первых, он работал. Вот прям без нареканий, не глючил, всё как часы. Разве что batch import можно оптимизировать (это мне работа на будущее), по моим прикидкам раз в 5-10, но и так терпимо.

Во-вторых использование DataScript очень, очень, очень упростило код. Архитектура простая: при старте мы грузим всю базу данных в браузер и потом все рендерим на клиенте. Формата особого нет — просто всё что есть вперемешку, на клиенте это суётся сразу в DataScript DB, и дальше работа делается над этой базой, включая сортировки, группировки, навигацию. Например, для каждого юзера считается количество разных типов ачивок — такая красная медалька — на лету, этой информации в дампе БД нет, есть только факты присвоения конкретного ачивмета конкретному человеку (select count group by, грубо говоря).

Переходы между страницами не обращаются к серверу вообще — вся информация уже есть, надо только развернуть ее правильным образом. Т.е., каждый тип страницы — это просто еще один/несколько запросов к одной и той же БД сырых фактов, которые все уже зафетчены на клиента.

Собственно, server api тоже никакого нет — просто один endpoint, /api/db/, который отдает всё. Мы не догадались сделать во время конкурса, но можно дамп БД генерить в виде файла и раздавать nginx-ом, благо у нас приложение малодинамичное.

Ну и что особо грело (опять же, мы во время конкурса не успели, но сейчас уже есть) это доставка изменений на клиента. Вот весь код обработки и перерисовки интерфейса по всем возможным пушам с сервера:

(let [url (str "ws://" (.. js/window -location -host) "/events")
      socket (js/WebSocket. url)]
  (set! (.-onmessage socket)
        (fn [event]
          (let [tx-data (read-transit (.-data event))]
            (d/transact! conn tx-data)))))

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

Производительность тоже вполне сносная. Сейчас я смотрю, что на проде в базу грузится 26K датомов (доходило и до ~50K, мы его периодически чистим), вставка — 800 мс (на проде старая версия, в новой там чуть оптимальнее сделано и есть прогресс-бар, так что юзер экспириенс не страдает. Плюс, bulk load я рано или поздно на порядок ускорю, и это еще меньшей проблемой должно стать). Еще у нас вывод юзеров на главной не лимитирован, мы просто всех выводим, там их сейчас 1200, соответственно рендер главной тормозит. Но в остальном достаточно быстро всё работает, на мой взгляд, страницы щелкаются, всё рисуется (каждый переход по странице — это несколько новых запросов в ДатаСкрипт + куча обращений к entity через атрибуты — это индекс лукапы, и их много).

Этого всего, конечно, не было бы, если бы не React. Эта вот легкость — «просто поменяй базу и всё» — ее не было бы, если бы не react и его «просто возьми базу и нарисуй всё». Да, каждая страница интерфейса рисуется полностью с нуля, включая выборку всех нужных для нее данных; нет даже тех оптимизаций, которые есть в Om/Quiescent с shouldComponentUpdate — и это вполне сносно работает.

Технологически мы повыпендривались немного, конечно. Для передачи данных клиент-сервер взяли Transit. Он чуть медленнее JSON (что, кстати, очень круто!), но сохраняет все кложевские структуры данных. Примерно такого порядка цифры на одних и тех же данных:

read-json:             8.338ms   1006 Kb
read-transit:         14.228ms    950 Kb
read-json + js->clj: 213.135ms   1006 Kb
read-edn:            358.302ms   1055 Kb

Т.е. если нужно передавать кейворды, сеты, даты (мы передаем даты, кстати, прозрачно абсолютно), ну или просто хочется получить персистентные мапы/вектора вместо JS-ных, кроме transit вариантов как-то и нет. (да, у нас мегабайт данных передавался на клиента, это те самые ~50K датомов, если я правильно помню, и всё работало, никто не умер (кроме, может, мобилок :)).

В зачетной версии core.async был для галочки, сейчас я его прикрутил следить за изменениями в БД и мультиплексировать их на веб-сокеты на сервере. Удобно.

Вот, буквально сейчас добавил еще и пару трансдюсеров. Работают вроде.

Да, ну и вот.

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

Да, весь смысл этого действа был в том, чтобы сделать ультра-портабельное приложение. Качаешь себе jar-ку, запускаешь ее и вуаля, всё в комплекте — веб-сервер, БД, git. У нас, в принципе, получилось. Ставьте у себя в компании, пробуйте на приватных репозиториях, экспериментируйте. Jar-ку можно взять в релизе.

И еще одно. Мы успели примерно треть от запланированных ачивок реализовать. Так что ждите апдейтов.

Желающие могут погадать, что это за ачивки:



  • 1
React это сила, конечно. Но я вот думаю о чём-то попроще и похардкорнее. Такая штука называется Kefir.

FRP это такая штука, хм, очень ограниченного применения. Т.е. можно придумать случаи, когда оно нужно и даже удобно. Но оно решает очень маленькую часть задачи. У меня здесь, например, нет ни динамики, ни источников данных, ничего. Есть флаг, на какую из трех страниц смотрит пользователь, и всё, это весь динамизм. Т.е. FRP тут будет или case по трем значениям — не влияет. А вот дальше начинается куча хардкора, где FRP толку с гулькин нос: выборка данных, группировка, рендеринг. Глупо притворяться, что этих задач нет и для них не нужно решение — оно нужно, и это не FRP.

Про ачивки:

1. закоммитил приватный ключ или пароль
4. вероятно многострочный (или > N строк) комментарий к коммиту
5. в тексте коммита использовал своё имя/никнейм/емейл

(Анонимно)
Закинул репу, но вышло так, что из-за багнутых имейлов получилось 4 аккаунта и их, видимо, почистили. Это как-то можно залечить?

Объединять разные имейлы мы не умеем. Почистили просто всех, мы периодически дропаем базу. Можно заново добавить :)

(Удалённый комментарий)
это поправлено в новой версии уже

Я подобную штуку приделал к гиту (только это были не ачивки) на Ractive + TaffyDB. И могу сказать что это весьма удобный подход (база в клиенте и тупые пакетные апдейты с/на сервер).

Да, только недостаточно освещенный как-то

а если обновятся данные на сервере, то что будет на клиенте, который уже все закэшировал ранее и сервер больше не дергает?

А там веб-сокет который держит в курсе посредством server push

хе-хе. У нас 29 мегабайт пакет в репозитории весит с виртуальной машиной =)

Спасибо за пример и за сырцы. Будет интересно посмотреть.

casino online bonus deposit situs casino online android online casino free spins utan insättnin

(Анонимно)
http://www.prowforum.pl/viewtopic.php?f=39&t=96244
http://giantcapital.co/forum/viewtopic.php?f=3&t=89570
http://www.power-roleplay.com/forum/index.php?topic=254355.new#new
http://fnatikx.com/viewtopic.php?f=45&t=9505
http://www.architecte-construction.com/forum/viewtopic.php?f=11&t=175333
http://www.nfsunlimited.net/forum/viewtopic.php?f=166&t=26699
http://oldbikecafe.it/forum/viewtopic.php?f=3&t=32896
http://forum.ahtuba.com/index.php?app=forums&module=post§ion=post&do=new_post&f=3
http://midwestprosound.startlogic.com/joomla36/forum/viewtopic.php?f=2&t=38273
http://bbs.sq5188.com/forum-40-1.html
http://forum.i2dom.ru/viewtopic.php?f=5&t=347617
http://help.dominanta.vpoloni.com/viewtopic.php?f=3&t=38381
http://www.trinkwasserforum.at/viewtopic.php?f=9&t=13356
http://www.cannabismacrography.com/viewtopic.php?f=20&t=146579
http://jailbreakromania.ro/backup-uri/forum%20backup/viewtopic.php?f=11&t=95287

  • 1