Couchbox

Jul. 27th, 2017 03:52 am
ermouth: (Default)

Месяц назад мы запустили публичную бету vezdelegko.ru, сервиса бронирования экскурсий, отелей и транспорта. Сервисы бронирования – сами по себе штука сложная, это как магазин, по которому надо вести учёт ассортимента на каждый день, причём ассортимент день ото дня меняется и цены зависят от дня и количества. Причём в магазине куча отделов, и партнёры сами управляют своим ассортиментом.

Дополнительно, в нашем случае сервис делался с прицелом на очень существенную масштабируемость как по ёмкости, так и по географии. Это автоматом предполагает архитектуру из многих узлов и распределённое хранение/обработку данных с последующей их репликацией и агрегацией. Под такую схему я придумал специальную архитектуру узла, которая потребовала платформы исполнения, это и есть Couchbox.

Снимок экрана 2017-07-27 в 2.26.24

География узлов и характер распространения данных предполагал версионированную мастер-мастер репликацию между узлами, по сложной топологии, различной для разных типов данных. Такие штуки прекрасно умеет делать моя любимая CouchDB, поэтому основной набор данных хранится в CouchDB, размазанный по всему графу узлов так, что все данные минимум дублированы.

Code follows data

Нативная CouchDB хранит в базах не только данные, но и код для predefined map/reduce запросов, по которым строятся высокоэффективные persistent индексы. Этот код, на JS или Erlang, хранится в документах рядом с данными и может распространятся между узлами в тех же потоках репликации, что и сами данные.

Couchbox, наша платформа, расширяет это всё механикой хуков, реагирующих на изменения документов в базе, и эндпоинтов – REST–концов, обрабатывающих входящие запросы через https. То-есть в те же специальные документы, где в обычной CouchDB живёт код функций индексов, для Couchbox-а можно добавить ещё и код функций хуков и внешних REST API эндпоинтов. Получается распределённая платформа приложений.

Особо примечателен факт, что с точки зрения установленного софта узлы не различаются вообще.

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

Файлы – это очень скучно

Важный момент, как именно код функций попадает в БД.

Код лямбд вообще не существует в виде исходных файлов. Он создаётся в специализированной среде разработки, основанной на CloudWall и Ddoc Lab. Выглядит это примерно так:

Снимок экрана 2017-07-27 в 3.52.11

То-есть, сорцы, из которых собираются лямбды, хранятся в PouchDB в браузерах разработчиков, реплицируются в CouchDB на какой-то из узлов, собираются, а затем распространяются по остальным узлам.

Деплой обновлений и скорость разработки

Такая архитектура расслаивается на три части по критерию обслуживания:

  1. Убунта, CouchDB, Redis, node.js и nginx – фундамент со временем между рестартами в месяцы. Для обновления или рестарта фундамента нужен доступ к каждому узлу через терминал.
  2. Couchbox – платформа приложений с временем между обновлениями сейчас в недели, скоро станет в месяцы. Разрабатывается на файловой системе в обычных IDE, для обновления на узлах нужен доступ через терминал.
  3. Код приложений, очень гибкий, может обновляться и дополняться с высокой частотой. Для разработки и отладки как клиентской (UI), так и серверной части (REST API) приложений не нужно ничего, кроме браузера. Код деплоится по узлам автоматом.

Общий объём кода, написанного в браузере для этой системы, перевалил за 100К SLOC и пока всё просто прекрасно. Стартскрин бэкэнда выглядит сейчас вот так:

Снимок-экрана-2017-07-27-в-4.29

Я, в общем, доволен – это самая сложная штуковина, которую я когда-либо придумывал, и её получилось не просто сделать как задумано, но ещё и в плановые сроки почти уложиться. Как с самой платформой, так и с приложениями на ней.

И да, Couchbox is MIT licensed. Опенсорц наше всё.

ermouth: (ang)
Лж-френд Никитонский в своём посте про полный абзац в вебе в смысле не просто поддержки стандартов, а вообще качества стандартов, немного иронически страдает.
Но самый стресс, конечно, от безнадеги. Если на сервере ты работаешь на технологии и страдаешь, то ты знаешь, что рядом есть компании, который пишут на чем-то хорошем, и когда-нибудь ты там окажешься. <…> А на фронте не так. Логики нет, и надежды никакой нет.
Я понимаю, но мнение не разделяю. Конечно, когда впервые в полный рост сталкиваешься со всем набором прелестей около-яваскриптной экосистемы, становится грустно. Кажется, что везде бардак, анархия и вообще «куда катится этот веб».

В самом деле это не бардак и не анархия. Так выглядит изобилие.

Замечу, что изобилие – нисколько не менее хищный зверь, чем аскеза. Изобилие порождает удивительно привлекательные, захватывающие – и при этом очень расточительные артефакты. Обычно они прекрасны снаружи, но очень капризны изнутри. Причём капризность, как и в реальном мире, мало зависит от простоты или сложности артефакта. Пока не попробуешь – не узнаешь.

Скажем, мне лично несколько раз крупно не везло с синтаксисом «код внутри разметки». Вот php там, angular, handlebars и всё такое. Да, xslt ещё. Сначала просто и красиво, но чуть отвернёшься – и кровавое месиво с костылями.

Чтобы не попадать постоянно на такие артефакты, достаточно соблюдать разумный консерватизм и умеренность. На пёстрый хайп интересно посмотреть с балкона – но не обязательно же в него вливаться. Ну не прямо же сразу, как минимум. Тем более, у изобилия есть два приятнейших момента:

А) Полно стабильных и проверенных артефактов. Хочешь rich controls, нормальные event-ы и ajax, работающие на чём угодно всегда – юзай jquery. Хочешь pub/sub и не париться про сокеты, лонгполлы и пр – юзай сокетио. Хочешь нормальную локальную базу – юзай localforage или pouchdb. То-есть, по аналогии с HAL (hardware abstraction layer) эти артефакты можно назвать BAL – browser abstraction layer.

Фуллстэк инженер – это не когда ты все комбинации всех чудес попробовал, а когда можешь этот самый фуллстэк средних масштабов собрать снизу до верху. И чтобы было дёшево, не ломалось, а если ломалось – легко чинилось, без необходимости продираться через слои транспайлеров, полифиллов и пр.

Б) Под вновь открытую проблему быстро появляется простое и эффективное лекарство. То-есть потом, когда-нибудь, эта новая проблема может и будет побеждена и искоренена во всей экосистеме – но можно не ждать светлого будущего, а жить в реальном мире.

Прямо как в жизни: новая болезнь – новая прививка, но если есть секта, которая прививки не делает по религиозным принципам – ну жаль очень. Нет большой разницы между прозелитством чисто функционального подхода и отказом от прививок потому что не благославляется, или там надеванием шапочки из станиоля. Это всё глупости, и не всегда безвредные.

В общем, изобилие – комфортнейшее состояние экосистемы, если быть консервативным и избирательным, но прощать хорошим вещам небольшие несовершенства.
ermouth: (ang)
По-хорошему, надо бы расписать тут длинную историю, почему внутрь модулей CommonJS не стóит пробрасывать лог-функцию, которая точно знает всю цепочку вызовов до модуля.

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

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

Вся суть модулей CommonJS – в однократной инициализации и потом быстрых вызовах уже проинициализированного кода. При замене контекста, естеснно, инициализацию в общем случае нужно повторять на каждый новый контекст. Это ничем не отличается от обычного инлайна кода – и полностью противоречит самой сути модулей.

Дополнительно при таком раскладе теряется часть контекста, которую модуль мог захотеть сохранять между вызовами. С одной стороны, никаких утечек памяти, а с другой... Вот любой кэш, например, это как раз управляемая утечка памяти.

В общем, с задачкой на логи я второй раз в жизни сталкиваюсь всерьёз, и во второй раз оказывается, что лог – очень особенный зверёк с инженерной точки зрения.

UPD. Нет худа без добра ) Функционал с контекстно зависимым логом и вообще полным пересозданием контекста мы решили сохранить, просто под другим именем. То-есть у нас будет require() и include().

Обычный require будет работать так же, как нодовский (и CouchDB-шный) CommonJS require. А вот include будет подключать модуль с расширенным контекстом.
ermouth: (ang)
В javascript ES6 появилась новая волшебная фича – прокси-объекты. К фиче не существует вменяемого polyfill-а в ES5, поэтому мы её до последнего времени не юзали. Её нет, например, в IE 11– и node.js 6–.

Фича работает примерно как в Java: выставляет перед объектом перехватчик, который позволяет реализовывать абстрактный интерфейс к объекту. Очень полезный функционал – lazy partial constructors там, контроль доступа к объектам в памяти, когда заранее неизвестно, какой код будет объекты обрабатывать, и всякое такое.

В общем, в конце прошлого года я решил, что время пришло.

Сейчас у нас в стадии поздней беты большой серверный компонент, который в существенной степени построен именно на прокси-объектах. То-есть там много однопоточных процессов, в каждом процессе выводок виртуальных машинок, а в каждой машинке по одному инстансу лямбды.

Собственно, вся эта кухня нагорожена для изоляции лямбд и их горячей замены. Код лямбд хранится в БД и распространяется по узлам в одном потоке репликации с данными, которые он должен обрабатывать. По приходу обновлений лямбд их надо а) заменять по-горячему, б) иметь pre-compiled образ для быстрого старта нескольких инстансов одной лямбды. Erlang inspired architecture.

Контекст (объект this) каждого вызова лямбды состоит из трёх частей, две из них приходят из БД, а третья – lazy плагины с файловой системы. Контекст между лямбдами частично shared. Целиком пересобирать здоровый объект перед каждым вызовом лямбды или дорого, или получается unsafe. Тут и пригодились Proxy-объекты.

По результатам всестороннего облизывания оказалось, что они чрезвычайно упрощают меж-VM-ное взаимодействие и вполне себе в ноде ужé быстрые (были адово медленные когда только появились).

Жаль, IE портит всю малину на клиенте. 
ermouth: (ang)
Запилил кроппер для мобилок, даже на видео заскринкастил. На ведроиде тоже прекрасно работает, поворот фоток я поборол. Домен есчо тестовый, там пусто.

Идея с пинчем двумя пальцами отвалилась кста не прожив и двух дней – по двум причинам.

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



Ещё я сегодня голыми руками (точнее, рукой) поймал на лету синицу. Мне на лоджию залетела – и оказалась настолько тупой, что как муха стала биться в стекло. Пока нёс до окна, чтобы выбросить, успел удивиться, что она перестала дёргаться сразу, как я её схватил. Наверное, подумла, что её уже съели )
ermouth: (Default)

Чемпионат идёт к завершению, поэтому расскажу как сайт устроен. Вообще это всё чистый couchapp, давно забытая в веках технология.

Couchapp – это когда есть CouchDB, и она для всего, а больше кроме CouchDB ничего и нет. Я в чистом виде так ещё не делал, всегда был node.js ещё как минимум. В этот раз node.js нет, но в архитектуру couchapp добавлено два слоя – JS rewrite на сервере и PouchDB на клиенте.

JS rewrite, только появившийся в CouchDB 2.0 моими и @kxepal трудами, позволяет делать сложный раутинг прямо внутри БД. То-есть кастомные API, access control и тп.

Вторая фича, PouchDB на клиентах бэкэнда, – позволяет делать тяжёлые веб-приложения бэкэнда с отзывчивостью десктопного уровня, ну и работать при плохих соединениях. “Тяжёлые” – это значит ворочать бинарными данными в мегабайты, картинки там обрабатывать, пдф-ки, сложные виджеты инлайнить с данными в реальном времени.

Архитектура одного узла выглядит так (может быть из одной, двух или трёх физ. машин):

Read more... )
ermouth: (ang)
Залипаю второй час уже. Совершенно офигительный тест на всякие tricky-штуки в js типа написать такие x, y, и z, чтобы (x && x==y && y==z && x!=z) ==> true.

http://alf.nu/ReturnTrue
ermouth: (Default)

Написал длиннющий пост про isomorphic apps – и у меня впервые за тыщу лет выпал LiveWriter, причем сразу с XP (да-да, я для LiveWriter-а спецом держу под Parallels-ом Windows XP, заодно там тёплый ламповый IE8 для тестов).

Наверное, это мне вселенная так говорит, что надо покороче написать пост )

В общем, главное было вовремя понять, что эффективнее всего писать такие приложения под дев-платформу, набитую фичами под завязку, а потом что получилось перекомпилировать.

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

Причин такого подхода две:

  1. Для рендера документа в ~статический HTML нужно гораздо меньше кода, чем для редактирования этого-же документа. Стало быть, “серверная” версия приложения может быть проще и быстрее – например, нам незачем обрабатывать события, поэтому код может быть синхронным.
  2. На бэкэнде (который offline ready) и в публичной части существенно различаются способы адресации бинари-ресурсов (картинки, документы для скачивания и тп). Картинки в режиме редактора, например, имеют уникальные каждый раз разные сессионные ObjectURL, а в публичной версии это простые всегда одинаковые пермалинки.

Overhead на такой подход в строках кода оказался неожиданно небольшой (~200SLOC для приложения в 300Кб JS) – но я вряд ли буду делать так часто.

Дело в том, что любой код, модифицирующий другой код, довольно hacky. Такой код требует тщательного обдумывания и аккуратного написания, и всё равно он от этого не становится “прозрачным”.

Более того, я не придумал какого-то разумного обобщения, позволяющего избежать ручного указания, что из исходного кода конкретного приложения оставить, что вырезать, а что трансформировать. То-есть, я придумал в самом деле – но тогда надо либо грузить на клиент туеву хучу лишних библиотек, либо сильно замедлять сервер лишними абстракциями.

В общем, интересно, но не серебряная пуля.

ermouth: (ang)
(При)открыли lesorub.pro – мы этот чемпионат типа продюсируем. Сайт пока с заглушками и плэйсхолдерами, рыхлый, неполный и вообще такой... угловатый – но пусть уже открытым висит.

С технологической точки зрения это проект интересен тем, что я впервые заимплементил почти в полный рост isomorphic-приложение, причём чрезвычайно сложное. То-есть, публичная версия рендерится на сервере тем-же кодом, с помощью которого в админке страница редактируется. Что, например, даёт полный WYSIWIG, вплоть до анимации.

Админка, как водится у нас в последнее время, offline first приложение. То-есть не только редактирование текста, но и редактирование/просмотр фоток и файлов вложений работает при отключенном интернете. Как только инет появляется, правки улетают на сервер и публикуются (если это не черновик), или прилетают с сервера, если кто-то редактирует.

На этом проекте я проверил применимость подхода offline-работы на существенных объмах данных, закэшированных локально в браузере – в проекте сотни мегабайт картинок, и на всех клиентах бэкэнда сервер поддерживает локальные копии ап ту дэйт в реальном времени. До этого я применял непрерывный sync только на коротких документах.

Третий умный термин – progressive rendering. Большинство страниц публичной части приходят сформированными так, чтобы как можно быстрее показать «первый экран». Остальное догружается по ходу пьесы. Из этого всего делается догрузка длинных страниц по мере промотки и непрерывный скролл по лентам материалов, не готово пока.

Может, успеем ещё вставить всякие интерактивные штуки, но тоже не уверен.

Ну и всякие параллаксы там, responsive вёрстка и тп плюшки – всё на месте. Может, даже 3Д-панорамы с коптера будут – уже готовы, но есть всякие обстоятельства.

Рыхлое блин только всё визуально, не хватает прихотливости.
ermouth: (Default)

Внезапно вчера в Архангельске прошла мегаконференция StartupStandup и, хоть меня туда и не приглашали (какой из меня стартапер, ога), один сделанный нами проект там внезапно оказался.

Паче чаяния, проект по итогам голосования был признан лучшим и даже заказчику приз какой-то дали от Ростелекома.

Коль скоро заказчик проекта его официально презентовал, правда, больше с бизнесовой стороны, не вижу причин не расказать о solovki.pro с колокольни разработчика. Несмотря на то, что всё только-только из-под Under construction выведено, за некоторые вещи “уже не стыдно” (с).

Фронтэнд

С точки зрения посетителя – это калькулятор туров на Соловки. Кулькулятор сразу туры продаёт, а не только считает. Заказ или уже можно оформить, или вот-вот можно будет, ждём от Сбера подтверждение включения платежного шлюза.

Туры кастомизированы – то-есть выбирается транспорт, проживание и развлечения на месте. Калькулятор устроен таким образом, что знает capacity каждого ресурса на каждую дату и даёт заказывать соразмерно возможностям принимающей стороны.

Снимок-экрана-2016-03-17-в-19.03

В самом деле это агрегатор, то-есть фактически услуги оказывают разные компании. Агрегатор аккумулирует данные о номенклатуре услуг и их загруженности и отображает это всё пользователю в виде калькулятора.

Capacity, к слову, считается на сервере одним единственным хитрым map/reduce-ом всего на 200- SLOC.

Калькулятор – jQuery.my приложение, 120 с небольшим кб в исходных текстах. Сделан в CloudWall, там же и отлажен. На картинке вот калькулятор исполняется в отладчике, в окошке.

Снимок экрана 2016-03-17 в 19.31.50

Приложение сложное, потому что надо учитывать кучу сценариев и пограничных случаев – и у меня нет уверенности, что мы учли их все, хотя старались.

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

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

Мобильную версию калькулятора пока не делали – заказчик посчитал, что подождёт.

Приложения бэкэнда

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

Веб-приложения бэкэнда с самого начала заточены под работу в сетях с ненадёжной и медленной связью, то-есть они offline-ready. Однажды загруженная вкладка с приложением прекрасно работает и без соединения и заказчивает/скачивает изменения в данных, когда оно появляется. С учётом качества связи в местах экологического туризма это не прихоть.

Когда соединение есть хотя бы плохонькое, в основном приложении данные обновляются моментально, есчо.

В самом деле приложения даже не знают, с каким набором данных они работают – всю синхронизацию за них делает платформа. Приложение просто делает this.db.get(), this.db.query() или this.db.put().

Например, вот так выглядит диспетчер со старыми тестовыми данными:

Снимок-экрана-2016-03-17-в-19.17

Окошки таскабельны, компоновка сделана под большие мониторы – чтобы можно было свободное поле вокруг календаря обвесить окошками. На мониторах поменьше и планшетах, правда, тоже нормально, просто не 7 дней помещается по ширине.

Из диспетчера можно отправлять СМСки и звонить – это важно, потому что климат на Соловках переменчивый и иногда надо туристов оперативно уведомлять.

Естессно, все приложения – манифесты jQuery.my.

Технологии

Особо детально не буду расписывать, потому что есть чувствительные данные в системе.

Серверная часть – node.js, патченная CouchDB и nginx. То-есть, основная часть кода на JS и немножко на Erlang-е. База крутится на SSD. Памяти на инстанс надо немного совсем. В общем, ничего необычного.

На админском бэкэнде смонтирован локальный CloudWall, который содержит все исходники и почти все средства разработки. CloudWall также обеспечивает эмуляцию рантайма клиентского бэкэнда – все пользовательские приложения запускаются с нативными данными прямо в IDE.

Вживую приложения бэкэнда исполняются прямо на клиентах и в большинстве случаев, когда дело не касается чувствительной информации, оперируют локальным – внутри браузера – working set’ом, который непрерывно синхронизируется с основным хранилищем.

Локальные данные позволяют трюки, которые затруднительны при обычной архитектуре – например, массивные map/reduce запросы. Вообще, серверные мощности бэкэнда очень скромны, потому что основной объём всякой тяжести вынесен в клиентские браузеры.

“Цена” поддержания канала постоянной синхронизации неожиданно невелика – примерно 14Кб в час, если новых данных не поступает/отправляется. Канал, кстати, гарантирует доставку в конечном итоге, сообщения не могут быть потеряны.

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

Сейчас вся эта конструкция выдерживает нагрузку согласно договору с кратным запасом, при необходимости масштабируется горизонтально на порядок-полтора просто наращиванием к-ва инстансов, для более существенной нагрузки надо уже посложней решение.

Поглядим, как это всё полетит )

UPD. Хехе, тут вот уже багов накидали. Аккурат на пограничные случаи. Поправили, но чует моё сердце, что это не последние.

ermouth: (Default)

Ой-вэй, не прошло и месяца, как обновление Javascript-компилятора выкатил webkit.org. То-есть там круто, ребята заменяют LLVM на что-то более узкоспециализированное.

https://webkit.org/blog/5852/introducing-the-b3-jit-compiler/

LLVM в вебкитовском Джаваскрипте используется(вался?) для оптимизации критических фрагментов кода. То-есть, упрощённо, сначала JS компилится совсем быстрым компилятором, а потом те фрагменты, которые активно используются во время рантайма, компилятся ещё раз с оптимизациями.

Вообще, LLVM очень крут, это звездная академическая разработка, очень тщательно вылизанная. Чем LLVM круче компиляторов, условно, предыдущего поколения можно в презентации вот посмотреть.

Тем не менее, вебкит решил, что можно сделать ещё круче, в одно базовое соображение: IR (intermediate representation, промежуточное представление) между двумя специализированными компиляторами может быть компактнее и проще полного IR LLVM.

Это похоже на историю с Флипбордом, который придумал собственный упрощённый DOM с рендером прямо в битмап на клиенте.

Новый IR называется B3 IR, в статье есть его описание и масса любопытных идей и наблюдений, из которых он родился. Вообще, оптимизации там такие… уж очень специфические. Если сравнивать с авиацией, это примерно как “мы сделали новые законцовки крыльев и экономим 1% топлива”. Но их там много и сразу.

С учётом того, что какие-то невообразимые совершенно ресурсы оказались задействованы в создании высокоэффективного JS-компилятора/рантайма сразу в нескольких существенных организациях, и жестокой конкуренции, я сделаю прогноз.

Думаю, в 2017 javascript overall превзойдёт Java по скорости.

И ещё один прогноз, уже совсем волюнтаристский. Думаю, к ~2020 мы увидим ОС, предположительно для IoT, в которой JS-engine будет на той же роли, на которой сейчас в Андроиде Dalvik.

ermouth: (Default)

Я вчера, уже когда засыпАл, пребывая под впечатление от Win95 на JS, размышлял, чего же не хватает, чтобы сделать из браузера условно-полноценную платформу для виртуализации. То-есть, сделать из браузера гипервизор.

В диктофон записалось “локалсторидж и юдипи”, после этого я уснул. Расшифровываю.

Синхронная файловая система

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

localStorage – единственная локальная браузерная БД, чтение/запись в которую синхронные. Главная проблема – localStorage крошечный, единицы мегабайт.

Есть ещё IndexedDB и уже считающаяся устаревшей (а напрасно) WebSQL – они дают объём до 1/10 диска на домен, но они обе асинхронные.

Synchronous XHR – синхронный ajax-запрос. Это сетевой запрос, а не локальный, стало быть сразу прилагается куча соответствующих проблем. Более того, Mozilla пометила синхронные ajax-запросы как deprecated.

В этой связи я предполагаю, что либо лимит на localStorage будет увеличен, либо появится какой-то новый механизм (либо адаптация имеющегося).

Про “адаптацию имеющегося” я говорю вот почему. В браузерах накоплено существенное количество самых разных технологий, которые могут очень неожиданно сочетаться. Например, btoa(unescape(encodeURIComponent(string))) служит для конвертации в base64 unicode-строк, и лишь единицы самых рафинированных экспертов впервые её увидев скажут вам, как и почему это вообще работает. Хотя все три функции – “системные” для браузера, их сочетание вводит в полный ступор сначала.

UDP

Сейчас в браузере нет никакого способа выполнять UDP-запросы. Я не думаю, что он появится, потому что такая возможность ставит под угрозу безопасность не конечного пользователя, а всей сети. Тем не менее, очевидно существует множество “классических” приложений, которым нужен UDP. Как тут быть, не очень понятно.

В браузере есть некоторое "идейное” подобие, чтоли – называется WebRTC. Эта технология предназначено для веб-версий “настольных” технологий, где UDP задействуется особенно широко. Потоковое видео, VoIP и тп.

Возможно, WebRTC будет как-то адаптирован под более широкового плана нужды.

Итого

Френды, если есть у вас какие-то навскидку соображения про фундаментальные ограничения на идею “браузер как гипервизор” – напишите плиз коммент.

ermouth: (Default)

В самом конце 2013 я с уверенностью предположил, что в 2014, максимум в 2015 мы увидим порт Win 95 под браузер.

Я ошибся на месяц, да.

Снимок-экрана-2016-02-01-в-17.06.17

https://win95.ajf.me/win95.html, я пробовал в Хроме. Время от времени сайт лежит – туда сегодня куча народу ломанулось.

Оно вообще довольно долго стартует – потому что выкачивает под 100Мб с черепашьей скоростью. Причём кэшируется примерно треть, остальные 2/3 выкачиваются на каждой перезагрузке страницы, ой вэй. Ну это легко поправить – и, я думаю, поправят.

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

То-есть “летать” – это значит никаких лагов вообще ни в чём интерфейсном. Звук на месте, приложения как надо работают, вот только на IE3  у меня упал, написал Uncaught SimulateInfiniteLoop.

19-летний чувак сделал. Я фигею.

ermouth: (Default)

Год начался по-високосному.

Для начала, у меня посреди зимы в зверскую сушь и морозяку (на улице –25, дома +25) зазеленела моя новогодняя ёлка, с верхушки. И, похоже, собирается цвести дальше вниз. Это вот называется “апикальный рост”:

IMG_1484

Ёлка у меня в горшке, примерно по пояс, Picea glauca conica, живая. Что зацвела – странно, эти ёлки очень капризные и не любят ни тепло, ни сухой воздух.

Два года назад у меня была такая же, правда, совсем маленькая, на подоконнике стояла – и засохла за пару месяцев. Интересно, что будет с этой.

Яваскриптовое опенсорц комьюнити внезапно тоже зимой “расцвело”. Я ожидал примерно чего-то такого в 2016, но не подряд, и не таких масштабов:

  1. Oracle выпустил JS-рантайм для JVM, причём по заявлениям довольно шустрый. Назвали Грааль (Graal).
  2. Microsoft заопенсорцила Chakra Core – JS-engine из IE11 и WinJS.

Эзотерические названия вполне закономерны, приличные JS-компиляторы уже давно ворочают минимум двумя уровнями intermedite representation и некоторые механики, скромно рисуемые вот на таких схемках как Bailout – чистый хак и магия.

chakracore_pipeline

То, что MSFT выложила свой JS-энджин в опенсорц для меня полная неожиданность. Там у них какой-то совсем тектонический сдвиг.

А вот то, что Oracle сделает в какой-то момент нормальную JS-машину я предполагал, но совершенно из сторонних соображений. Дело в том, что HotSpot вырос из компилятора Smalltalk’а под названием Strongtalk. Который придумал чувак по имени Ларс Бак 20 лет назад.

Он же, неожиданно, придумал Google V8 – самый быстрый JS-компилятор до недавнего времени. Все основные идеи в V8 – родом из Strongtalk’а. Раз эти идеи породили отличный JS-компилятор в одном месте, странно было бы, если б они не выросли во что-то похожее где-то ещё.

Конвергентная эволюция, да. Нисколько не удивлюсь, если найду в Чакре в том месте, что изображено загнутой стрелкой Bailout, те же идеи, кстати.

Апикальный рост начинается примерно одновременно сразу в нескольких местах, ога )

ermouth: (Default)

Отрелизил сабж, релиз больше про рефакторинг/оптимизацию. Проковырялся неделю вечерами с профайлером, открыл много нового про GC и скорость регэкспов. Вот примерчик особенно злодейский:

Снимок экрана 2015-12-12 в 4.39.41

Попутно напишу вот про виджет с заглавной, оч хорошо на нём видно и что такое $.my, и что я там оптимизировал. Пример, собсно, по клику на картинку.

Снимок экрана 2015-12-12 в 4.28.49

В примере 100 строк кода, 2Кб, это с HTML-ем уже. Эти 2 Кб грузят внешние данные и делают из них master/detail.

Особая фишка – в левой колонке позиции таскабельны. И номера обновляются по мере перетаскивания, причём если справа открыта карточка и тыкнуто в поле ввода, то фокус не теряется.

Ну и если справа начать имя править, слева оно немедленно рефлектится. Причём можно даже начать тащить айтем слева и одновременно печатать справа )

Кто делал что-нибудь похожее хоть раз в жизни, знает, что 100 строк кода на такое – это вообще наглухо магия.

Инициализация этого виджета с 280 строками данных (каждая из которых – тоже форма) занимает примерно 300мс. По 1мс на форму. Флеймчарты до и после оптимизаций:

Снимок экрана 2015-12-12 в 5.57.37

Снимок экрана 2015-12-12 в 5.57.20

В самом деле 1мс – это чрезвычайно дохрена. Мы на каждую строку слева инциализируем по сути маленькое приложение, и это дорого. Увы, такой подход можно наоптимизировать ещё примерно только раза в 2 и будет потолок.

Но у меня есть план Б.

В jQuery.my 2.0 будет другой (точнее, ещё один) алгоритм. Во-первых, просто сам старт одинаковых форм станет быстрее, потому что полуфабрикат формы будет кэшироваться. А во-вторых, рендерить я их буду чанками.

Подход с чанками у меня уже 3 года как реализован для длинных списков отдельным плагином и в бою обкатан, надо только вкрутить. Это уже в 2016 будет.

Завтра-послезавтра days off.

ermouth: (ang)
Я в прошлую пятницу решил, что мне надо попробовать поконтрибутить в CouchDB кодом. Там есть несколько фич, который не поддерживаются текущими участниками, и которые явно стоило бы развивать.

Дело было за малым:

  1. Подтянуть Эрланг до уровня, чтобы начать на нём писáть (читал я код на Эрланге более-менее и до этого)

  2. Скачать git CouchDB и сделать так, чтобы он собрался и скомпилился

  3. Вкрутить свой функционал

  4. Написать тесты.

Собсно, самый сложный был второй пункт. Как водится в опенсорце, количество зависимостей просто потрясает воображение, и далеко не все ставятся и настраиваются без бубна. Вишенкой на торте была зависимость от TeX (2.5 гига), который нужен только, чтобы сделать парочку PDF-ов документации.

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

Короче просто скомпилить с сорцев, чтобы заработало, заняло у меня три дня о_О. С учётом, что я ненавижу CLI всей душой, не так и много, хотя я думал, что управлюсь за два.

Зато вот третий пункт – написать работающий код – занял всего два дня вместо трёх. Глядя на имеющийся код пишется полегче. Правда, пока производительность того, что написалось, оставляет желать много лучшего, но я работаю. У меня там переключение между процессами (вызов JS VM из Erlang-кода), а это ой дорого.

Такие дела.

Ddoc Lab

Jul. 30th, 2015 11:31 pm
ermouth: (ang)

Зарелизил CloudWall 1.8, в который вошло новое приложение – Ddoc Lab.

Для этого приложения, выведенного стэндэлоном, сделал отдельный сайтик. Сейчас инглиш вычитывается и пытаюсь пофиксить merchant-account на пэйпэле (дичайший гимор). А так всё уже работает в хорошем приближении.

Клик по картинке – на сайт.

Снимок экрана 2015-07-30 в 23.10.38

Софтинка – довольно специализированное IDE, так что уважаемым читателям бложека вряд ли будут интересны подробности. А вот технологии под ним поинтересней.

Софтинка эта написана в полном CloudWall-е, а на сайте работает под его порезанной стэндэлон-версией. То-есть теперь у меня есть такая специальная версия CloudWall, которая поддерживает всего одно приложение и одну открытую БД на вкладку. И есть генератор этой мини-версии из большого CloudWall-а, да.

То-есть это позволяет релизить сингл пэкиджом из одного JSON-файла сразу и приложение, и ОС под ним. Этот JSON можно копипастить как документ в CouchDB – и приложение сразу взлетает на той базе, куда скопипащено.

Ещё заодно пробую “Pay what you want” модель монетизации – Ddoc Lab в виде JSON-а в некоторых случаях может быть просто бесценен ) То-есть это можно приложение поставить себе в CouchDB  в один копипэйст буквально – и заиметь человечий редактор индекс-функций и приложений у себя локально.

Такие дела.

ermouth: (ang)

Написал за ночь сегодня логгер для следующеего релиза CloudWall, сейчас потестил – оч шустро вышло. Написал заметочку в корпоративной Стене и решил сюда кросспостнуть.

Под катом инженерные соображения про логгер для браузерной системы.

Клик чтобы раскрыть... )

Пока копировал псто, подумал ещё, что надо сделать фичу распознавания повторяющихся событий. И, может, это выпилить отдельной стэндэлон-библиотекой и на гитхаб сложить.

Справочно: скорость записи в localStorage небольших фрагментов (десятки килобайт) колоссальна: на моём i7 – сотни мегабайт в секунду в любом браузере. Это многократно превосходит среднюю скорость сериализации в JSON, например.

Коллеги, что я забыл про важные фичи лога?

ermouth: (Default)

У Гугла есть отличный сервис – PageSpeed Insights. Сегодня посравнивали dvinanews.ru – новостной ресурс местного правительства – с флагманами типа rbc.ru, lenta.ru, meduza.io и с несколькими менее значимыми.

Моя прекрасная FEED CMS уделывает по десктопной версии их всех )

Снимок экрана 2015-06-25 в 22.12.26

По мобильной версии – всех, кроме Медузы. У Медузы – 100 из 100 по удобству и чуть больше, чем у Двинаньюса, по коду.

Снимок экрана 2015-06-25 в 22.12.42

Сравнение с новостными сайтами правительств других субъектов РФ можно даже не приводить – их Двинаньюс опережает с бооольшим отрывом. Включая регионы с дикими бюджетами, типа Татарстана. И даже kremlin.ru – правда, всего на один балл.

От гордости просто разрывает ) Редчайший так то случай, когда правительственный ресурс опережает коммерческие проекты по качеству инженерного исполнения. Про архитектуру, админку и всякое такое я писал вот тут ermouth.livejournal.com/604509.html

Скоро кста откроем новостной ресурс ещё для одного субъекта, красивенький.

И да, если у уважаемых читателей из других регионов РФ есть на примете СМИ или пресс-центры с хорошей посещаемостью, в которых работают нормальные ребята, а инженерное/дизайнерское исполнение убогое – дайте им ссылочку на этот пост.

Месяца за три можно любой пресс-центр превратить в конфетку – причём мы не только в инженерном плане сделаем по-хорошему, но и редакцию круто подтянем по уровню.

И это не зарубежной выделки платформа, FEED сделан в России )

UPD. КДПВ вот придумалась )

feedvsother

ermouth: (ang)
Последнюю неделю я практически рыл носом землю, чтобы понять точно, что же вызвало потерю данных. Нашёл и зафайлил кучу багов разной степени тяжести в PouchDB, но ручное прикрытие каждого так и не давало ответа, в чём же в самом деле причина.

Апофеоз истории вот тут https://github.com/pouchdb/pouchdb/issues/3961. В результате я написал тест, который имитирует, что происходит в cloudwall без запуска cloudwall – но оказалось, что этот тест никто кроме меня не может воспроизвести. А у меня он железно воспроизводился на двух моих Маках в 100% случаев – но только для двух доменов, для остальных доменов всё было ок. Я даже стал подозревать в какой-то момент, что зелёные человечки – не выдумка (шучу :)

Ключик в решению проблемы увиделся, когда я слил свои файлы IndexedDB из Хрома разработчику PouchDB, и он не смог воспроизвести баг даже с ними. Просто ничего больше не осталось, как грешить на файловую систему – всё остальное было к тому моменту тщательнейшим образом проверено и отброшено.

Так и оказалось – на обоих Маках у меня были сбои на FS. На эйре, видимо, деградировал SSD, а на iMac – HDD, который часть Fusion Drive. Именно поэтому баг и не проявлялся, пока не закроешь вкладку в Хроме – браузер закрывал файл, а файловая система его обнуляла из-за ошибок в бинарном дереве каталога.

Любопытно, что проверка при запущенных ОС не показывала мне никаких проблем с дисками. Для обнаружения проблем надо было перезагрузить обе машины и запустить проверку диска по-холодному. После исправления дисков и удаления вручную каталогов с базами данных баг перестал воспроизводиться.

Из этого надо вынести несколько уроков:

  1. БД ни при каких обстоятельствах не должна считать нижележащую технологию надёжной. А так считают и PouchDB, и IndexedDB и, увы мне, CloudWall.

  2. При обнаружении багов с потерей данных идти надо начинать снизу вверх, а не сверху вниз. Это тот-же ровно принцип, как и в случае с проверкой розетки, питания и предохранителей в первую очередь, когда «компьютер сломался». Я как-то не соотносил эту народную мудрость с высокими технологиями, а напрасно.

  3. Баг – лучший учитель. Я за последнюю неделю досконально разобрался, как устроен PouchDB  в части репликации, внешних ajаx-запросов и взаимодействия с IndexedDB. Попутно разобрался со схемой запросов к IDB по-хорошему (ну и гадость, доложу я вам), с производительностью IDB, с тем, как устроены файлы каталогов в HFS+, и много ещё чего попутного по мелочи.

Такие дела. Извинился перед чуваками за наезд – хотя он бесспорно был небесполезен. Я ясно вижу, что они меняют и тесты, и сам подход.

Profile

ermouth: (Default)
ermouth

July 2017

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526 272829
3031     

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 27th, 2017 04:34 am
Powered by Dreamwidth Studios