Показаны сообщения с ярлыком OpenSource. Показать все сообщения
Показаны сообщения с ярлыком OpenSource. Показать все сообщения

пятница, 17 июня 2022 г.

[work.open-source.anger] А давайте подсчитаем чужие деньги или почему не стоит смотреть зубы дареному коню

По случаю тяпницы позволю себе тригернуться на комментарий к последней статье о SObjectizer на Хабре. Вот этот комментарий:

Ещё б документация была б хорошая, а не вот это месиво доксигена. Ну и в туториалах на gh кросс-ссылки и вычитку английского, а то встречаются там местами штуки типа "бесплатных функций" (free functions).

Простите мне мой французский, но мне кажется, что многие просто не понимают, во что обходится по деньгам разработка проекта "за свои".

пятница, 13 мая 2022 г.

[open-source.sad-humour] Идея о том, как заставить платить за поддержку и развитие OpenSource проекта

Навеяно вот этим, и вот этой статьей на Хабре: Что происходит с лицензиями в open source.

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

И если для крупного OpenSource, масштаба GCC или KDE, все еще не так печально (как мне кажется), то вот для мелких OpenSource-проектов с условной тысячей звезд на GitHub-е и несколькими десятками внедрений хоть сколько-нибудь радужных перспектив нет от слова совсем.

К чему-то это в конце-концов приведет, но вот к чему и когда? ХЗ.

Однако, по поводу тяпницы, да еще и дня программиста (да-да, сегодня тяпница-тринадцатое, наш неформальный праздник!) позволю себе поделиться одной странной идеей.

Года три назад помогали одному клиенту привести в чувство старую программулину. У которой не было никаких тестов.

Ну т.е. вообще никаких. Ни unit-тестов, ни каких-либо тестовых скриптов, ни каких-либо тестовых/имитационных стендов. Вообще Н-И-Ч-Е-Г-О.

Признаться, я такого с 1990-х не видел.

Внесение изменений в код было похоже на ходьбу по минному полю :)

Тогда-то я очень хорошо понял, что полностью доступные исходники -- это всего лишь полдела. Но когда у тебя вообще нет тестов (даже так: когда тестов нет ВООБЩЕ), то заниматься сопровождением кода становится ну очень грустно. А был бы проект больше и сложнее, то и невозможно.

Отсюда и идея: держать на github-е в публичном репозитории только исходники базовой функциональности (+ примеры, если речь идет о библиотеке). Тогда как исходники всех тестов будут жить в приватном репозитории, который доступен только владельцам проекта.

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

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

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

пятница, 6 мая 2022 г.

[open.source] Простите, что-то меня триггернуло нипадецки

Сегодня увидел на RSDN:

цинк. Речь идет о наследии Сергея Садовникова, который ушел из жизни от ковида два года назад.

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

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

В 2016-ом мы с коллегами создали свою компанию именно с целью предоставления поддержки для собственных OpenSource разработок. Чтобы у тех, кто выбирает наши инструменты, была возможность заплатить небольшую копеечку и поиметь гарантии того, что проект не будет заброшен, а на найденные проблемы будут оперативно реагировать.

Это нифига не сработало. Никто не хотел (и не хочет) ничего платить (было всего лишь одно или два исключения).

Мы попытались двигать один из продуктов под двойной лицензией. Со стоимостью лицензии на одного пользователя всего в 80USD за год.

Это нифига не сработало. Никто не хотел ничего платить.

В конце-концов в 2021-ом году я пустился на совсем уж вынужденный шаг и стал просить у крупных компаний спонсорской помощи на развитие OpenSource. Хотя бы в размере 200USD в год.

Это нифига не сработало.

Соответственно, мы делали и, местами, еще делаем собственный OpenSource исключительно за собственный счет.

На энтузиазме.

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

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


На правах проплаченной рекламы: возможно кому-то пригодятся услуги паталогического велосипедостроителя и хронического программиста-камиказде, в анамнезе которого есть SObjectizer, RESTinio, json-dto и arataga. Как говорится, друг все еще интересуется...

вторник, 2 февраля 2021 г.

[soft.business] Послесловие к неудачной попытке найти внешнее финансирование для RESTinio/SObjectizer/so5extra

На данный момент история с поиском финансирования закончилась ничем. Развитие наших OpenSource-проектов приостановлено. Попробуем поднакопить средства на заказной разработке/консультациях, чтобы затем вернуться к работам над RESTinio/SObjectizer/so5extra.

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

Суть в том, что у SObjectizer-а и у RESTinio совершенно разные ситуации.

SObjectizer старый и устоявшийся программный продукт. Далеко не самый популярный и известный. Если его следующий релиз выйдет в конце 2021-го или даже в начале 2022-го, то отрицательно на SObjectizer-е это вряд ли скажется. А если и скажется, то не сильно.

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

В конце 2020-го года мы попали в ситуацию, которая, по хорошему, требует оперативного разрешения: проект http-parser, использующийся в RESTinio, остался без сопровождения. Соответственно, чтобы не зависеть от проекта без поддержки, RESTinio нужно сменить парсер HTTP-протокола на что-то другое.

Добавим сюда еще и то, что для успешной конкуренции с аналогичными проектами RESTinio очень желательно было бы иметь поддержку не только http/1.1, но и хотя бы http/2.

И если уж менять http-parser на что-то другое, то можно было бы под этим соусом добавить в RESTinio и http/2. А если получится, то и заложить возможность последующего добавления http/3.

Сложно сказать, во что бы это все вылилось по трудозатратам. Но по первым впечатлениям, от 3 до 5 месяцев это могло бы занять. Тут нужно учитывать, что мы стараемся тщательно тестировать RESTinio, писать примеры и расширять документацию. Это такая работа, которая может быть не видна, но которая должна быть выполнена, и которая занимает изрядное время. Поэтому если кому-то кажется, что 3-5 месяца для написания собственной поддержки http/1.1 и http/2 -- это слишком много, то мне лишь остается позавидовать вашей производительности и трудолюбию.

Итого, если начать работы над RESTinio-0.7 сейчас и вести их не отрываясь ни на что другое, то выкатить новую версию получится лишь где-то к лету 2021-го.

В прошлом году мы рассчитывали заработать на arataga, также в начале весны маячили на горизонте новые заказы. Но ничего этого не случилось. Поэтому у нас сейчас нет денег на то, чтобы вложиться в разработку следующей версии RESTinio.

Мы встали перед выбором: либо заняться заказной разработкой и остановить развитие RESTinio на какое-то время, либо же поискать внешние вложения.

Остановка развития RESTinio выглядела слишком рискованно. Сперва RESTinio будет заморожен на 5-6 месяцев, затем в течении еще 3-5 месяцев будет вестись разработка новой версии с релизом RESTinio-0.7 где-то через год... Отличная перспектива чтобы закопать проект.

Поэтому мы решились на поиск внешнего финансирования.

Фактически, мы пошли с протянутой рукой. Мол, сами мы не местные, помогите кто чем может.

Варианты с платной техподдержкой и "рекламными услугами" были выбраны по следующим причинам:

1. В РБ (да и в РФ) нельзя просто так взять и внести деньги на счет коммерческой структуры. Поступление денег должно быть оформлено договором. Лучше всего, если это договор на оказание каких-то услуг или на выполнение каких-то работ. Техподдержка и "рекламные услуги" как раз и являются теми формами договорных отношений, которые позволяют нам получать деньги ровно за то, что мы и делаем. И не требуют от нас ничего больше, за исключением оформления некоторого количества дополнительных бумажек раз в квартал (в виде актов по выполненным работам).

2. Суммы мы выбрали такие, которые крупные (и даже не очень крупные) компании могут выложить не задумываясь. Грубо говоря, в компании с несколькими тысячами сотрудников 150USD в квартал отдел маркетинга может запросто потратить просто "на скрепки". Мы надеялись, что сумма в 600USD в год для крупного производителя софта будет достаточно мизерной для того, чтобы ответственные люди могли дать добро на помощь нашим открытым проектам не заморачиваясь на то, что мы можем дать взамен.

Если же называть вещи своими именами, то мы рассчитывали на благотворительность.

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

Эта ставка не сыграла. Внешнего финансирования мы не нашли. На техподдержку согласилась всего одна компания из тех, что используют наши открытые продукты. Ни одного положительного ответа на "рекламные услуги" в предлагаемой нами форме нет, хотя есть несколько другие варианты, но они еще требуют проработки с неочевидным для всех выхлопом.

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

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

PS. Если какая-то компания хочет вложиться в разработку RESTinio/SObjectizer/so5extra (например, хочет поиметь какую-то специфическую функциональность), то давайте пообщаемся на eao197 на gmail тчк com. Можно обсуждать различные варианты сотрудничества.

понедельник, 25 января 2021 г.

[soft.business] Ищу финансирование для развития RESTinio/SObjectizer/so5extra

Наша совсем маленькая компания stiffstream на протяжении нескольких лет делает такие OpenSource инструменты для С++ как:

  • RESTinio: встраиваемый HTTP/WebSocket сервер, ориентированный на эффективную асинхронную обработку входящих HTTP-запросов;
  • SObjectizer/so5extra: реализация Actor Model, Publish-Subscribe и Communicating Sequential Processes, существенно упрощающая разработку сложных многопоточных приложений.

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

К сожалению, кризис 2020-го ударил и по нам. Наши собственные финансовые ресурсы для развития RESTinio и SObjectizer/so5extra практически исчерпаны.

Поэтому мы приостанавливаем работы над этими проектами на неопределенный срок.

UPD. На данный момент история с поиском финансирования закончилась ничем. Развитие наших OpenSource-проектов пока приостановлено. Мы попробуем поднакопить средства на заказной разработке/консультациях, чтобы затем вернуться к работам над RESTinio/SObjectizer/so5extra. Кому интересно, вот послесловие к этой затее.

Соответственно, те предложения, которые были первоначально описаны в этом посте, стали не актуальны. Я спрятал их под кат, сохранив просто для истории.

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

[prog.c++] Текущие хотелки по SObjectizer/so5extra

Две недели назад был пост о том, что хотелось бы поиметь в RESTinio. Попытаюсь сформулировать что-то подобное и в отношении SObjectizer+so5extra.

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

На данный момент я вижу два направления, в рамках которых можно произвести НИОКР и, если в сухом остатке получится приемлемый результат, перенести результаты исследований в SObjectizer.


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

Суть в том, что сейчас агенты в SObjectizer-е работают в соответствии с push-моделью.

Это значит, что когда вы отсылаете сообщение в mbox, то обычный mbox запихивает заявку на обработку сообщения в очередь событий агента. Рано или поздно дело доходит до обработки этой заявки: диспетчер владеет очередью событий и именно диспетчер извлекает очередную заявку из этой очереди. При этом mbox, который сформировал заявку, не знает когда именно это произойдет.

Push-модель проста, понятна, эффективна и подходит для огромного количества случаев.

Однако бывают моменты, когда агенту выгоднее использовать pull-модель.

Первый сценарий, который можно закрыть посредством pull-модели -- это поддержка приоритетов для заявок (см. недавнюю статью на Habr-е на эту тему). Причем такая поддержка, которая бы позволила использовать приоритеты заявок совместно с базовыми штатными диспетчерами SObjectizer-а, которые изначально для этого вообще не предназначались (например, one_thread, active_obj, active_group, thread_pool, а также asio_thread_pool и asio_one_thread из so5extra).

Второй сценарий -- это еще одно возможное решение проблемы producer-consumer, которое давеча обсуждалось в issue на GitHub-е. Идея в том, что специализированный mbox собирает отосланные в него сообщения, но не сразу отсылает сообщения в очереди событий агентов, а хранит у себя до тех пор, пока какой-то из consumer-ов не освободится и не обратиться за следующим сообщением. В этом случае pull-модель выглядит предпочтительнее push-модели.

Третий сценарий -- это возможность агента читать сообщения напрямую из mchain-а как из обычного mbox-а. Дело в том, что mchain-ы задумывались как средство передачи информации от агентов наружу, в те части приложения, которые написаны без SObjectizer-а (в обратную сторону отлично работают старые-добрые mbox-ы). И в этом качестве они работают отлично. Но иногда их хочется использовать и для общения агентов между собой. А вот тут не все так хорошо, поскольку нет простого и эффективного способа проинформировать агента, заинтересованного в чтении сообщений из mchain-а, о том, что в mchain-е есть информация и можно вызывать receive.

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

Четвертый сценарий -- это возможность сделать поддержку чего-то вроде selective receive (например, по аналогии с механизмом Stash из Akka). Правда, я не уверен, что это действительно реализуемо. Но, думается, что pull-модель предоставляет здесь несколько больше шансов на успех, нежели push-модель.

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


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

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

Временами это не есть хорошо. Например, если пользователь хочет создать 100500 агентов, привязанных к active_obj-диспетчеру (т.е. работающих на собственных рабочих нитях), но при этом желает ограничить размер стека для каждой из рабочих нитей всего 32KiB. Работай пользователь напрямую с POSIX threads у него была бы такая возможность. А вот штатные диспетчеры не позволяют это сделать.

Другой сценарий: пользователь хочет поиграться с приоритетами рабочих нитей. Например, создать one_thread-диспетчер с высоким приоритетом рабочей нити. И thread_pool-диспетчер с низкоприоритетными рабочими нитями. Опять же, на чистом POSIX threads API это можно было бы сделать. А через штатные диспетчеры SO-5 -- нет.

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

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

Нужно сказать, что диспетчеры asio_one_thread и asio_thread_pool из so5extra позволяют в свойствах диспетчера задать тип для рабочей нити. Так что эти два диспетчера позволяют пользователю реализовывать рабочие нити вручную со всеми нужными свойствами, тогда как основная внутренняя логика работы диспетчера остается на нашей (т.е. мейнтенеров SO-5) совести.

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


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

Так что если вы хотели бы видеть что-то в SObjectizer-е, что могло бы облегчить вам вашу работу, то скажите об этом нам. Например, через issues или discussions на GitHub-е.

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


Наверное, немного странно записывать хотелки когда вопрос о финансировании работ для наших OpenSource проектов еще не решен. И непонятно когда мы сможем вернуться к работе над RESTinio/SObjectizer.

Но, во-первых, этот пост нужен мне самому как "зарубка на память". Будет от чего оттолкнуться когда представится возможность вернуться к SObjectizer-у.

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

[work.opensource.c++] arataga: что это вообще и зачем мы публикуем это в OpenSource?

arataga -- это работающий прототип socks5+http/1.1 прокси сервера, который мы в прошлом году разрабатывали для одного из наших клиентов. К сожалению, этот прототип остался невостребованным. Ну а чтобы не пропадать добру и самопиара ради, мы решили открыть его исходники.

Как все развивалось

Дело было так: с 2019-го года мы работали с заказчиком, который эксплуатировал у себя некий старый прокси-сервер. Весьма старый, написанный с применением модели thread-per-connection, да еще и оставшийся без сопровождения. Собственно, мы как раз и занимались его доработкой под нужды заказчика.

Где-то к концу весны 2020-го стало понятно, что больше ничего хорошего из этого прокси-сервера не выжать. Что нужно его заменять на что-то новое, написанное с нуля или же переделанное готовое (типа nginx или envoy после обработки напильником).

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

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

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

Наши обязательства перед клиентом закончились. У нас на руках остался arataga и с этим нужно было что-то делать. Например, выбросить и забыть. Или же открыть.

Зачем нужно было делать arataga?

У заказчика были следующие и, как мне представляется, местами весьма специфические условия:

суббота, 9 января 2021 г.

[prog.c++] Пару слов про позиционирование RESTinio и основные хотелки для RESTinio на 2021-й

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

ИМХО, уже пришла пора более точно определиться с позиционированием RESTinio в экосистеме C++. Это раньше RESTinio был молодой и мало кому известной разработкой. Сейчас же ситуация меняется, мы уже не молоды ;)

Позиционирование важно потому, что на данный момент можно насчитать с дюжину подобных инструментов для C++. И хотя на слуху находится всего пара-тройка названий, но если какой-то C++ разработчик захочет подобрать встраиваемый HTTP-сервер под свою задачу, то у него будет приличный выбор на любой вкус, цвет и размер кошелька. Конкурировать со всеми и во всех направлениях бессмысленно. Посему следует обозначить нишу для RESTinio.

Мне представляется, что RESTinio уникален тем, что под одной крышей здесь собрано:

  • простота использования RESTinio для каких-то очевидных и понятных действий. Так, чтобы получить запрос и пройтись по списку HTTP-полей, не нужно выписывать вручную процедуры чтения данных из сокета;
  • гибкая настройка RESTinio под условия пользователя. Захотел пользователь применять Boost.Log для логирования? Нет проблем, RESTinio позволяет написать адаптер и RESTinio будет логировать свои действия с помощью этого адаптера. Или, например, захотел пользователь запускать вместе с RESTinio на io_context еще и какие-то свои сетевые операции... Опять же, нет проблем;
  • набор инструментов, которые позволяют применять RESTinio для каких-то нетривиальных сценариев. Например, средства работы с HTTP-заголовками используются в arataga даже для исходящих HTTP-запросов.

Что делает RESTinio хорошим выбором для ситуаций, когда разработчику нужно что-то сильно повыше уровнем, чем Boost.Beast, но при этом хочется иметь гораздо больший контроль за происходящим, чем в oat++ или cpp-httplib.

Отличный пример такой задачи, на мой взгляд, -- это прокси-сервер типа arataga. На Boost.Beast его делать будет слишком хлопотно. А oat++/cpp-httplib вряд ли дадут доступ к своим потрохам.

Именно в этом направлении, думаю, и стоит развивать RESTinio дальше.

Т.е., RESTinio должен быть выше уровнем, чем Boost.Beast, но ниже, чем oat++ и cpp-httplib. Но при этом средствами RESTinio продвинутый разработчик с небольшими усилиями должен уметь создать для себя что-то похожее на oat++/cpp-httplib, но заточенное под специфические требования конкретной прикладной задачи.

Или же, в более лаконичной форме:

RESTinio должен стать конструктором из продвинутых инструментов, отлично подогнанных друг к другу.

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


Теперь попробую обозначить несколько приоритетов в предполагаемом развитии RESTinio в 2021-ом году.

Во-первых, это замена http_parser на что-то другое. Конечно же, хочется иметь собственную реализацию, которая бы a) сделала RESTinio полностью header-only библиотекой, и b) поддерживала бы различные тонкие моменты в HTTP-протоколе (вроде chunk extensions). Если это не получится, то рассмотреть и внедрить какую-то готовую альтернативную реализацию (llhttp, picohttpparser, что-то еще).

Во-вторых, добавление режима работы в котором RESTinio не будет загружать весь запрос в память перед вызовом обработчика, а будет отдавать читаемые от клиента данные кусками по мере их поступления. Это позволит a) эффективно обрабатывать запросы с большим объемом входящих данных, и b) использовать RESTinio для сценариев, в которых сейчас RESTinio не может применяться в принципе (например, для разработки прокси-сервисов).

В-третьих, добавление поддержки http/2. Пока RESTinio жестко завязана на работу со всего лишь один протокол. От этого нужно уходить, т.к. рано или поздно, http/2 и http/3 вытеснят http/1.1. И если в 2021-ом получится изменить RESTinio так, чтобы в нем поддерживалось сразу два протокола, то это откроет отличную возможность добавить со временем еще и http/3, а может и еще что-нибудь.

Если в 2021-ом получится реализовать в RESTinio все эти три хотелки, то это будет очень хороший результат. Если получится. Но для этого нужны условия. Впрочем, об этом поговорим через несколько дней.

По поводу поддержки в RESTinio клиента я могу лишь повторить то, что уже говорил раньше: без внешнего финансирования мы поднять такую задачу не сможем. Так что если кто-то готов вложить в RESTinio, минимально, 3.5K USD, то давайте всерьез обсудим такую возможность.


Если кого-то интересует перечень встраиваемых HTTP-серверов для C++, то выглядит он приблизительно так (перечисление в случайном порядке): RESTinio, Boost.Beast, cpp-httplib, http_backend, Pistache, RestBed, served, C++ REST SDK, proxygen, Simple-Web-Server, drogon, oat++

среда, 21 октября 2020 г.

[prog.c++] json_dto-0.2.11 released

json_dto is a thin wrapper around RapidJSON library we wrote several years ago. It's surprising for us that this small bicycle is used by someone outside our team. Sometimes users show us use-cases we just weren't thinking about. And we add new features to json_dto to fulfill expectations.

The last updates to json_dto add a possibility to customize formatting of (de)serialized values by specifying custom Reader_Writers. For example let's imagine that we have a struct with a `std::map<std::uint32_t, int>` field:

struct example_data {
   std::map<std::uint32_tint> m_weights;
   ...
};

It's impossible to write a simple (de)serialization code for example_data in the form:

struct example_data {
   std::map<std::uint32_tint> m_weights;
   ...

   template<typename Io> void json_io(Io & io) {
      io & json_dto::mandatory("weights", m_weights)
         ...
         ;
   }
};

because RapidJSON expects string values as keys, but json_dto (de)serializes `std::uint32_t` as integers. And the naive implementation of `json_io` shown above leads to run-time error during serialization.

Now json_dto allows to use custom formatters for fields to be (de)serialized:

struct simple_reader_writer {
   // Those methods will be used for (de)serializing of map's keys.
   void read(
      json_dto::mutable_map_key_t<std::uint32_t> & key,
      const rapidjson::Value & from) {
      ... // Deserializing key from a string.
   }
   void write(
      const json_dto::mutable_map_key_t<std::uint32_t> & key,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      ... // Serializing key as a string.
   }

   // Those methods will be used for (de)serializing of map's values.
   void read(
      int & v,
      const rapidjson::Value & from) {
      json_dto::read_json_value(v, from); // Just reuse json_dto.
   }
   void write(
      const int & v,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      json_dto::write_json_value(v, to, allocator); // Just reuse json_dto.
   }
};

struct example_data {
   std::map<std::uint32_tint> m_weights;
   ...

   template<typename Io> void json_io(Io & io) {
      io & json_dto::mandatory(
              // Explicit specification of custom Reader_Writer for that field.
              // The usage of apply_to_content_t tells that custom formatter
              // should be applied to every item of the container.
              json_dto::apply_to_content_t<simple_reader_writer>{},
              "weights", m_weights)
         ...
         ;
   }
};

So now keys of `example_data::m_weights` will be (de)serialized as strings.

But custom Reader_Writers allow to go further. Let's imaging that `example_data` contains yet another `std::map<uint32_t, int>`:

struct example_data {
   std::map<std::uint32_tint> m_weights;
   std::map<std::uint32_tint> m_colors;
   ...
};

where keys of `example_data::m_colors` should be represented in the form `#xxxxxx`, where `xxxxxx` is hexadecimal representation.

We can create another custom Reader_Writer:

struct color_hex_reader_writer {
   // Those methods will be used for (de)serializing of map's keys.
   void read(
      json_dto::mutable_map_key_t<std::uint32_t> & key,
      const rapidjson::Value & from) {
      ... // Deserializing key from a string.
   }
   void write(
      const json_dto::mutable_map_key_t<std::uint32_t> & key,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      ... // Serializing key as a string.
   }

   // Those methods will be used for (de)serializing of map's values.
   void read(
      int & v,
      const rapidjson::Value & from) {
      json_dto::read_json_value(v, from); // Just reuse json_dto.
   }
   void write(
      const int & v,
      rapidjson::Value & to,
      rapidjson::MemoryPoolAllocator<> & allocator) {
      json_dto::write_json_value(v, to, allocator); // Just reuse json_dto.
   }
};

and use it for (de)serialization of `example_data::m_colors`:

struct example_data {
   std::map<std::uint32_tint> m_weights;
   std::map<std::uint32_tint> m_colors;
   ...

   template<typename Io> void json_io(Io & io) {
      io & json_dto::mandatory(
              json_dto::apply_to_content_t<simple_reader_writer>{},
              "weights", m_weights)
         & json_dto::mandatory(
              json_dto::apply_to_content_t<color_hex_reader_writer>{},
              "colors", m_colors)
         ...
         ;
   }
};

The full working example can be seen here.

PS. I don't like to answer questions like "Is json_dto better than nlohmann::json, cereal or any other similar library?" We started to use RapidJSON several years ago and we didn't know about many of the JSON-libraries well known today. At some time we decided to simplify our marriage with RapidJSON and wrote json_dto. Since then it's easier for us to continue to use json_dto than to switch to any other library. So if you are happy with nlohmann::json there is no need to see for something else. But if you have to stay out of nlohmann::json for any reason there is json_dto ;)

PPS. We love reinventing bikes and we know how to do it: RESTinio and SObjectizer are also out of our garage.

среда, 30 сентября 2020 г.

[prog.opensource] c-smile собирает средства на перевод sciter в OpenSource

На RSDN в свое время был (а может и есть сейчас) такой участник: c-smile. Один из тех немногих старожилов RSDN-а, об общении с которым остались хорошие впечатления.

Так вот, уже много лет c-smile делает в одиночку проект sciter. Это встраиваемый HTML/CSS движок, который может использоваться для разработки легковесных GUI-интерфейсов на базе Web-технологий.

Оказывается, в середине сентября c-smile открыл на Kikstarter-е компанию по сбору средств для перевода sciter в категорию OpenSource: Open Source Sciter Engine.

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

пятница, 8 мая 2020 г.

[prog.c++] Теперь и SObjectizer, и RESTinio перечислены в списке Awesome C++

В общем-то мелочь (на самом деле нет), а очень приятно: теперь и SObjectizer, и RESTinio перечислены в важном для C++сообщества списке Awesome C++.

Для нас, как разработчиков SObjectizer и RESTinio, это важно потому, что в мире C++ люди нередко начинают поиск подходящих для себя инструментов именно с Awesome C++. В этом смысле Awesome C++ -- это нечто вроде "желтых страниц". И теперь оба наших основных OpenSource продукта на этих "желтых страницах" перечислены.

RESTinio в Awesome C++ попал достаточно бысто. А вот включения туда SObjectizer-а пришлось ждать в течении нескольких лет. Поэтому большое спасибо всем тем, кто отдал свой голос за добавление наших разработок в этот престижный список!


Как обычно добавлю, что мы очень внимательно относимся ко всем пожеланиям и предложениям наших пользователей. Поэтому если вам чего-то не хватает в SObjectizer/so5extra, RESTinio или json_dto, то дайте нам знать. Постараемся учесть ваше мнение.

Так же, если у кого-то есть сложности в освоении и/или использовании SObjectizer и RESTinio, то не стесняйтесь, спрашивайте. Обязательно поможем. И еще с большим энтузиазмом поможем вам, если вы решите заказать у нас разработку, в которой будут использованы SObjectizer или RESTinio ;)

пятница, 3 апреля 2020 г.

[software.thoughts] Интересно и толково про проблемы OpenSource

На RSDN-е всплыла интересная ссылка: https://youtu.be/YDBE7OM7-mM?t=35578. Это доклад Андрея Ситника на HolyJS 2019 Piter. Доклад как бы из двух частей: первая часть про OpenSource, а вторая, якобы, про Web. Но мне показалось, то обе части доклада посвящены одной и той же проблеме. И то, что автор доклада рассказывает про ситуацию c front-end-ом, можно без особых проблем перенести на любую другую область разработки софта.

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

Одна из основных мыслей, высказанных Андреем Ситником, а именно "популярность != надежности/качеству", может показаться провотиворечащей реальности. Но здесь я, скорее, склонен с автором согласиться. С той лишь поправкой, что для популярного инструмента гораздо легче найти в Интернете рецепты для простых задач и решения для простых, наиболее часто встречающихся проблем. Так что если вам с помощью популярного инструмента нужно решать какие-то типовые и несложные задачи, то вероятность сделать это "малой кровью" все-таки больше, чем если выбирать мало известный инструмент.

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

Еще очень важная вещь, которая проистекает из рассказанного Андреем Ситником -- это необходимость помощи в раскрутке малоизвестных OpenSource проектов. Может показаться мелочью, но каждая звездочка на GitHub-е, каждый лайк в соцсетях, каждый дополнительный +1 на Reddit-е или HackerNews, не говоря уже о ретвитах/репостах оказывают огромную помощь разработчикам малоизвестных OpenSource проектов. Т.к. отсутствие этих мелких признаков внимания очень сильно снижают мотивацию разработчиков. Поэтому если вам на глаза попадается новость о каком-то OpenSource проекте, который показался вам интересным или просто симпатичным, то не сочтите за труд, лайкните эту новость. А если вы еще и сделаете ее репост где-нибудь от своего имени, то реально сделаете большое дело.

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

Но, с другой стороны, у разработки OpenSource нет нормальной экономической модели. Т.к. если не брать 1% топовых открытых проектов, которые либо спонсируются (прямо или косвенно) различными компаниями, либо смогли выйти на окупаемость за счет модели двойного лицензирования или продажи техподдержки, то подавляющее количество открытых проектов -- это либо в прямом смысле one-man show, либо результат работы совсем небольших коллективов. И жизнеспособность таких небольших проектов в условиях кризиса является далеко не праздным вопросом.

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

Не факт, что такая тенденция уже сформировалась. И даже если сформировалась, то ощутимые последствия станут заметны в относительно отдаленной перспективе (лет через 10-15).

В общем, еще раз порекомендую посмотреть доклад. Он будет интересен даже тем, кто далек от разработки front-end-а. Т.к. рассказывает о более важных и общих вещах.

Я же напоследок дам еще одну интересную ссылку: Seven Stages of Open Software. ИМХО, имеет смысл с этими стадиями ознакомиться перед тем, как ввязываться в открытие своего кода и подумать, а до какой стадии ты сам хотел бы дойти.

вторник, 24 января 2017 г.

[prog.c++] Исходники эксперимента mosquitto_transport на BitBucket-е

Где-то с год назад попробовали сделать эксперимент: написали на SObjectizer небольшую обертку над mosquitto. Написали, попробовали каково это, поиспользовали для прототипирования. И забыли :)

Теперь вот вспомнили. Чуток причесали и открыли исходники на BitBucket-е: mosquitto_transport-0.6.

Обертка самая простая. SSL не поддерживаем. Сообщения с QoS выше 0 -- не поддерживаем. За счет того, что libmosquitto, как мне показалось, с Windows не дружит, то работает это все только под Unix-ами (мы проверяли только под Linux-ами).

Цель эксперимента была в том, чтобы посмотреть, насколько просто будет подружить разработку на SObjectizer с использованием MQTT в качестве транспорта. А т.к. MQTT -- это всего лишь протокол передачи данных, который не определяет, как именно будут упакованы сами пользовательские данные, то мы еще хотели сделать так, чтобы mosquitto_transport не был привязан к конкретному типу encoding-а. В общем, все цели были достигнуты. Использовать MQTT можно, получается довольно удобно (по крайней мере на мой взгляд). Разные типы encoding-а подключаются посредством несложной шаблонной магии (подробнее я писал об этом в прошлом году). У себя мы использовали JSON-encoding (посредством rapidjson и json_dto, о json_dto Коля Гродзицкий рассказывал на Corehard C++ Autumn 2016).

Разве что быстро стало понятно, что libmosquitto не есть хорошо. Во-первых, libmosquitto заточен под однопоточную синхронную обработку MQ-шных сообщений. Т.е. когда приходит сообщение, вызывается соответствующий callback и при возврате из него libmosquitto сразу же начинает обработку QoS. Т.е., если сообщение пришло с QoS выше 0, то факт успешного возврата из callback-а воспринимается libmosquitto как факт успешной доставки и подтверждение получения. Что делает невозможным длительную асинхронную обработку сообщений. Во-вторых, исходники libmosquitto оставляют печальное впечатление, да и нам их пришлось патчить, чтобы можно было использовать libmosquitto-овский event-loop в многопоточном окружении (поэтому, кстати, mosquitto_transport использует пропатченную мной версию libmosquitto, а не оригинальную). В-третьих, хотелось бы больше кроссплатформенности.

В общем, mosquitto_transport сделали на libmosqitto, в самом libmosquitto разочаровались, начали делать свою реализацию MQTT. Но пришлось пока это дело заморозить. Может быть к весне получится разморозить.

Еще нужно добавить, что mosquitto_transport для управления зависимостями использует MxxRu::externals. Так что для того, чтобы собрать, нужно воспользоваться MxxRu. Приносим свои извинения, но нам так было удобнее, да и сам mosquitto_transport вряд ли кому-то потребуется. Поэтому адаптацию под какие-то другие менеджеры зависимостей для C++ (коих, по сути-то и нет), мы не делали. Да, еще нужен Boost, но Boost через MxxRu::externals мы не подключали (еще раз лучи поноса Boost-оводам, которым, блин, нравятся ну очень большие архивы и которые, блин, не знают, что такое нормальная модульность). Так что Boost нужно ставить либо вручную, либо через систему пакетов конкретного дистрибутива Linux-а.

Ну вот как-то так. Сам mosquitto_transport работает стабильно, но развивать мы его вряд ли будем. Скорее это станет основой для нашего собственного MQTT-шного транспорта для SObjectizer. Но если есть какие-то вопросы или замечания, или предложения, то всегда пожалуйста: выслушаем, ответим, прислушаемся... :)

четверг, 18 июня 2015 г.

[prog] Говорят, что SourceForge скатывается в полную Ж. Но что в этом хорошего?

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

четверг, 9 апреля 2015 г.

[prog.opensource] Реализация MD5 на чистом C++11. Just For Fun :)

При реализации примера md5_bruteforce обнаружил, что практически все актуальные реализации MD5 находятся в больших или не очень больших библиотеках (вроде OpenSSL, PolarSSL, Crypto++, Botan, POCO и т.д.) И если отдельно лежащую, без лишних зависимостей, версию MD5 на чистом С еще можно найти, то вот с C++ными вариантами дело было плохо. Поэтому, взяв за основу код из POCO, сделал свое.

Получился один hpp-файл. В зависимостях только стандартная библиотека C++11. Проверял под MSVS2013, GCC 4.9.2 (Win, Linux), clang 3.4.1 (FreeBSD), clang 3.6.0 (Linux). (Upd. На длинных последовательностях (больше 4GiB), тоже проверял, работает, по крайней мере в 64-битном режиме).

Лицензия -- трехпунктная BSD + лицензия POCO + лицензия от RSA Data Security. Вроде как все OpenSource-ое, допускающее использование в любых проектах, в том числе и закрытых.

Сама реализация лежит здесь. Там же полный "проект", в котором все проверялось. Все под Svn, поскольку мне так удобнее. Если у кого-то будет время и желание взять и разместить где-то еще -- буду только рад.

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

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

четверг, 11 сентября 2014 г.

[prog.c++] Кстати о реализации спинлоков на основе стандартной библиотеки C++11

У меня внутри SObjectizer валяется, по-сути, полностью автономная, header-only библиотека с реализацией single-reader/single-writer и multi-reader/single-writer спинлоков: spinlocks.hpp.

Базируется она на информации из документации к стандартной библиотеке C++11, идеях Дмитрия Вьюкова (так же известного как remark, одного из ведущих разработчиков Thread Sanitizer, невероятно крутого гуру в области многопоточности), исходных текстов LLVM и libcds. Собственно, код rw_spinlock, это калька с реализации аналогичного спинлока Димы из LLVM.

Так вот, если у кого-то будет интерес, то можно будет выделить spinlocks.hpp в отдельный подпроект, снабдить его примерами, более развернутой документаций. И публиковать ее релизы и дистрибутивы рядом, но отдельно от SObjectizer-а. Получится такая легковесная библиотека со spinlock-ами, базирующаяся только на стандартной библиотеке C++11, без дополнительных внешних зависимостей.

Итак, интересно/нужно это кому-то?

Если интересно или нужно, то какое имя будет подходить этой библиотеке? Например, stdcxx_spinlocks/stdcxx_spins/cxx11_spinlocks/cxxspinlocks?