Русский
Русский
English
Статистика
Реклама

Open source

Новый плагин CrowdSec для защиты сайтов на WordPress

17.02.2021 12:10:47 | Автор: admin

Всем привет! Мы активно работаем над развитием нашей системы блокировки нежелательных IP-адресов и сегодня рады рассказать сообществу о нашей новой разработке плагине WordPress для упрощения жизни веб-мастеров и защиты администрируемых ими сайтов.

Как и многие другие наши решения, новый баунсер для WordPress опенсорсная разработка, которую мы распространяем под лицензией MIT. Распространяем мы его в виде официально подтвержденного WordPress-плагина. Ознакомиться со страницей нашей разработки и скачать его можно на официальном сайте WordPress.

Новый баунсер CrowdSec для WordPress решает сразу две задачи веб-мастера: отсекает нежелательные IP-адреса и имеет дополнительную функцию более мягкой блокировки показывает нежелательным или подозрительным IP-адресам капчу.

Для того, чтобы плагин работал, вам, как и в случае отдельно взятого сервера или сети, нужно будет установить серверную часть CrowdSec. Ранее мы уже публиковали небольшой туториал на эту тему, почитать можно тут. Наш плагин для WordPress совместим с версиями CrowdSec 1.0.х, то есть с последними актуальными релизами после нашего большого обновления, в котором мы провели рефакторинг архитектуры и перешли на использование API вместо прямых обращений элементов системы к БД.

Flex Mode

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

CrowdSec достаточно мощный инструмент, как и любой другой проект в этой сфере, а перманентный бан по IP-адресу не шутка.

Именно для того, чтобы веб-мастер по незнанию или не внимательности не сделал непоправимое, мы создали Flex Mode для плагина WordPress.

Flex Mode это щадящий режим работы баунсера и сервера с сайтом. В этом режиме владелец подозрительного IP-адреса не может получить перманентный бан. Максимум ограничений доступа к сайту для такого посетителя заключается в необходимости пройти капчу.

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

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

А вот так уже кастомизированная:

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

Баланс защиты и производительности

У нашего плагина есть два режима поддержания связи с серверной частью CrowdSec.

Первый режим по умолчанию "Live mode". Это режим, в котором баунсер при обращении к сайту нового пользователя в режиме реального времени обращается к API сервера для получения информации. В том числе, в этом режиме, IP посетителя сайта проверяется и по общему бан-листу CrowdSec, который генерируется с нашей стороны как разработчиков. После этого сервер передает информацию обратно баунсеру в плагине и он уже банит/не банит пользователя, или показывает ему капчу.

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

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

Он называется "Stream Mode" и работает по обратному принципу, нежели "Live Mode". При включении режима поточной работы, главным инициатором выгрузки бан-листа становится серверная часть, которая с определенной периодичностью просто обновляет списки на стороне баунсера, позволяя тому работать с большей автономией.

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

Если вы используете CDN, обратный прокси или балансировщик нагрузки, вы сможете указать в настройках баунсера диапазоны IP-адресов этих устройств. Это позволит вам проверять IP-адреса ваших пользователей. Для других IP-адресов баунсер не будет доверять заголовку X-Forwarded-For.

Что будет дальше

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

Новый плагин мы протестировали на большинстве версий WordPress, которые сейчас актуальны в мире. В общей сложности, тестами мы покрыли 90%, если верить статистике использования WP по миру. Также мы проводили тестирование на PHP версий 7.2, 7.3, 7.4 и 8, чтобы исключить конфликты на уровне языка, на котором написан WordPress. Само собой, с выходом новых версий как движка, так и языка программирование, мы продолжим работу в этом направлении.

Повторимся, что плагин выпущен под лицензией MIT самой свободной и широкой бесплатной лицензией в мире. Исходный код плагина полностью доступен на GitHub, как и исходный код CrowdSec.

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

Подробнее..

Перевод Обратная сторона Open Source-славы как угрожают автору curl

23.02.2021 14:15:47 | Автор: admin

Прим. перев.: уникальная история, что всколыхнула интернет в эти дни, показывает неожиданную сторону того, что могут заслужить авторы самых популярных Open Source-проектов. Ниже представлен перевод недавней заметки из блога шведского программиста Daniel Stenberg оригинального автора и главного разработчика curl, обладателя премии Polhem Prize (вручается в Швеции за выдающиеся инженерные достижения).

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

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

Увы, не все эти письма забавны.

Категория: не смешно

Сегодня я получил следующее письмо:

От: Al Nocai <[скрыто]@icloud.com>

Дата: Пт, 19 Фев 2021 03:02:24 -0600

Тема: Я тебя убью

Да, именно такая тема (I will slaughter you).

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

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

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

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

Я решил, что имя в письме выдуманное, а адрес электронной почты, скорее всего, одноразовый. Часовой пояс в строке с датой намекал на Центральное стандартное время США, но, конечно, мог быть подделкой, как и все остальное.

Мой ответ

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

Это письмо совершенно и абсолютно неприемлемо, и оно глубоко ранило меня. Вам должно быть стыдно! Подумайте о том, чтобы пересмотреть свои манеры.

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

Очевидно, что вы не достойны моего кода.

Впрочем, я не надеялся, что мой ответ будет прочитан или что-то изменит.

Примечание: Обновление ниже добавлено после первоначальной публикации.

Ответ Al Nocai

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

Мне плевать. Твое дерьмовое ПО послужило вектором атаки, из-за которой я потерял многомиллионный оборонный проект.

Они использовали твое дерьмовое ПО, чтобы украсть root у меня и у многих других. Из-за этого только на прототипировании я потерял более 15 тысяч долларов.

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

Знаешь, что я сделал, чтобы заслужить это? Я пытался разработать торговый путь в сфере технологий и разработать методики обучения на основе проектов, чтобы детки были при деле. И знаешь, кто во всех этих файлах? Ты. Это отвратительно. Меня взломали в октябре 2020, перехватив трафик федерального сервера, и всем этим я обязан тебе.

Мне пришлось сидеть и смотреть вот на это:

1. fireeye в октябре 2020;
2. Solarwinds в октябре 2020;
3. взлом модемов Zyxel в октябре 2020;
4. множество векторов атаки на Sigover с помощью XML injection;
5. стохастическая шаблонизация в JS с использованием выражений сравнения для записи в регистры данных;
6. 50-миллиардные компании охотятся за мной, поскольку я разоблачил их дерьмовое вредоносное ПО.

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

Ты построил гоночный болид для Формулы-1, а ключи бросил шпане с раздутым эго. А теперь из-за всего этого мусора мне приходится разбираться с уязвимостями нулевого дня в Win10.

Я потерял свою семью, свою страну, своих друзей, свой дом и 6 лет работы, пытаясь построить лучшее будущее для потомков. И во всем этом виноват твой код. Этот код используется для того, чтобы похищать root и внедрять эксплойты. Этот код используется для шантажа.

Так что я ни капельки не расстроен. Ты прекрасно представлял себе возможности этого кода. И думал, что все это большая шутка. А я не смеюсь. Я уже давно прошел эту точку. /- Al

Al продолжает

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

Письмо 3:

https://davidkrider.com/i-will-slaughter-you-daniel-haxx-se/

Валяй. Ты меня не испугаешь. Что привело меня сюда? 5-е покушение на мою жизнь. Условия предоставления услуг Apple? Иди к черту со своей платформой.

Забавно, что он нашел публикацию о заметке в моем блоге.

Письмо 4:

Есть проект: Анализ риска военных операций в урбанизированной местности с помощью широкополосного анализа электромагнитного спектра с использованием различных преобразований Фурье.Ты и этот David Krider, кем бы он ни был, вы часть всего этого.

- Взломы федеральных серверов;
- соучастие в покушение на убийство;
- мошенничество;
и т.д.

На данный момент я разговаривал с ФБР, региональным отделением ФБР, министерством по делам ветеранов США (VA), офисом генерального инспектора VA, Федеральной комиссией по связи (FCC), Комиссией по ценным бумагам (SEC), АНБ, Минздравом (DOH), Управлением служб общего назначения (GSA), МВД, ЦРУ, Бюро финансовой защиты потребителей (CFPB), Министерством жилищного строительства и городского развития (HUD), MS, Convercent; по состоянию на сегодня представители 22 отдельных ведомств вызванивают меня и тратят мое время.

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

(Прим. перев.: в английском варианте сохранено своеобразное форматирование и опечатки.)

К письму 4 также был приложен PDF-файл с названием BustyBabes 4.pdf. Он представляет собой 13-страничный документ о NERVEBUS NERVOUS SYSTEM. Первый параграф гласит: NerveBus Nervous System призвана быть универсальной платформой для всестороннего и комплексного анализа, предоставляя конечному пользователю целостную, связную и реальную информацию о среде, которую тот мониторит. В документе не упоминается ни curl, ни мое имя.

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

Дополнительная информация

Тема на Hacker news и Reddit.

Я сообщил об угрозе в шведскую полицию (по месту жительства).

P.S. от переводчика

В то время, как в комментариях Hacker News обсуждают, что приведенный в письме список обвинений (где упомянуты FireEye, SolarWinds и т.п.) набор бессмысленных фраз (что, возможно, указывает на психические отклонения), в комментарии к публикации в блоге Daniel Krider можно найти некоторые уточнения по этому поводу от самого автора:

I have since October, had my entire life sandboxed by individual Daniel Patrick Ehrlich to find software loopholes to aid in development of SCNR, an aggregation bot for Open Source Intelligence tied to Subverse Media and Timothy Pool, the Journalist.

I know the following:
1. React JS primary utility is to obfuscate URIs to inject malicious code
2. This code is commonly down my user agents, KHTML, primarily Favicons as they are the SVG type, and carry injectable XML.
3. Qualcom BT Adapters and drivers are routinely hacked via the SigOver attack vector through malicious sub packet injection.

P.P.S.

Читайте также в нашем блоге:

Подробнее..

На что соглашается человек, когда разрешает все куки

25.02.2021 00:07:45 | Автор: admin
Люди не читают инструкций. Вы почти наверняка не читали лицензионное соглашение Windows, не читали лицензионное соглашение iTunes, не читали условия Linux GPL или любого другого программного обеспечения.

Это нормально. Такова наша природа.

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



Большинство нажимает Согласиться и продолжает жить как ни в чём ни бывало. Никто ведь не читает политику конфиденциальности, верно?

Разработчик Конрад Акунга (Conrad Akunga) решил разобраться, какие конкретно условия предусмотрены соглашением об использовании. Для примера он взял новостной сайт Reuters. Это абсолютно произвольный пример, у большинства других сайтов тоже есть свои правила.

Вот эти правила:


Обратите внимание на полосу прокрутки. Дальше идёт продолжение.

Ещё шесть экранов с текстом











Если вкратце, документ информирует пользователя о нескольких вещах:

  • Что веб-сайт собирает и обрабатывает данные
  • Что для этого он работает с различными партнёрами
  • Что сайт хранит некоторые данные на вашем устройстве с помощью файлов cookie
  • Что некоторые файлы cookie строго необходимы (определяется сайтом). Их нельзя отключить.
  • Некоторые персональные данные могут быть проданы партнёрам для предоставления соответствующего контента
  • Вы можете персонализировать рекламу, но не удалить её

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

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

И ещё один пункт о партнёрах, которым продаются ваши персональные данные. Список партнёров общий для всех сайтов, которые сотрудничают с IAB.

Кто же эти партнёры?

Если нажать на соответствующую кнопку, то появится следующее окно:


Обратите внимание, насколько маленький ползунок на полосе прокрутки. Наверное, там их сотни. Под названием каждой компании ссылка на политику конфиденциальности.


Это не одна и та же ссылка, а разные! Каждая из них ведёт на уникальную политику конфиденциальности каждого партнёра. Сколько человек на самом деле пойдёт по этим ссылкам вручную, чтобы прочитать условия? Это просто нереально.

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



Скопированный список он вставил в VSCode и получил огромный файл на 3835 строк, который после форматирования (Alt + Shift + F) разбился в чудовище на 54 399 строк.



Конрад написал программку, которая с помощью регулярных выражений извлекает нужные фрагменты данных названия компаний с URL и генерирует результат в формате Markdown по шаблону.

Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger();// Define the regex to extact vendor and urlvar reg = new Regex("\"vendor-title\">(?<company>.*?)<.*?vendor-privacy-notice\".*?href=\"(?<url>.*?)\"",RegexOptions.Compiled);// Load the vendors into a string, and replace all newlines with spaces to mitigate// formatting issues from irregular use of the newlinevar vendors = File.ReadAllText("vendors.html").Replace(Environment.NewLine, " ");// Match against the vendors html filevar matches = reg.Matches(vendors);Log.Information("There were {num} matches", matches.Count);// extract the vendor number, name and their url, ordering by the name first.var vendorInfo = matches.OrderBy(match => match.Groups["company"].Value).Select((match, index) =>new{Index = index + 1,Name = match.Groups["company"].Value,URL = match.Groups["url"].Value});// Create a string builder to progressively build the markdownvar sb = new StringBuilder();// Append headerssb.AppendLine($"Listing As At 30 December 2020 08:10 GMT");sb.AppendLine();sb.AppendLine("|-|Vendor| URL |");sb.AppendLine("|---|---|---|");// Append the vendor detailsforeach (var vendor in vendorInfo)sb.AppendLine($"|{vendor.Index}|{vendor.Name}|[{vendor.URL}]({vendor.URL})|");// Delete existing markdown file, if presentif (File.Exists("vendors.md"))File.Delete("vendors.md");//Write markdown to fileFile.WriteAllText("vendors.md", sb.ToString());

В результате получился список всех партнёров, и у каждой свой уникальный документ c условиями конфиденциальности. Вот этот список: vendors.md.

В нём 647 компаний.

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

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

Код для парсинга из этой статьи опубликован на Github.
Подробнее..

Интернет вещей по-русски. Процедура активации OpenUNB

28.02.2021 12:13:00 | Автор: admin

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


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


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


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


В OpenUNB активация устройства производится пользователем. Также необходим доверенный канал между пользователем и сервером сети. Схема взаимодействия представлена ниже:


image


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


В стадии "запрос на активацию" пользователь должен по служебному каналу отправить на сервер запрос на активацию, в котором передается идентификатор DevID активируемого конечного устройства. Если активация возможна, то сервер сообщает об этом. Далее пользователь делает "запуск процедуры активации на устройстве". Это может быть пакет по радио-интерфейсу или другому, удобному. Это также может быть нажатие кнопки "активация" или просто включение питания устройства. После этого события устройство передает "служебный пакет активации", в котором содержится номер текущей активации.


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


Рассмотрим подробно процедуру со стороны устройства и со стороны сервера.


Со стороны устройства процедура выглядит так:


  1. проверяется текущее значение счетчика активаций Na. Если счетчик активаций уже достиг максимально возможного значения, то данное устройство больше не может использоваться, и выключается;
  2. увеличивается значение счетчика активаций: Na = Na + 1;
  3. вырабатывается ключ активации Ka;
  4. вырабатывается ключ расчета имитовставки Km для эпохи Ne = 0;
  5. формируется служебный пакет активации, в поле MACPayload которого содержится текущее значение счетчика активаций Na, а в качестве адреса указывается DevAddr0 = CRC24(DevID). При этом поле MACPayload передается в открытом виде (не шифруется), а поле имитовставки MIC рассчитывается на ключе Km для номера Nn = 0. Сформированный служебный пакет активации должен быть отправлен MAX_PKT_TX_NUM раз подряд для повышения вероятности его доведения;
  6. устройство считает активацию успешно завершенной и может передавать пакеты полезных данных.

Напомним формат пакета OpenUNB:
image


Сервер по приему пакета активации ищет адрес из пакета в списке адресов активированных устройств. Для каждого из найденных совпадений:


  1. сохраняется полученное значение счетчика активаций устройства Na. Если для данного устройства ранее уже осуществлялась успешная активация, то сервер должен дополнительно проверить, что текущее значение Na больше чем значение Na, полученное при предыдущей успешной активации. Если эта проверка завершается неуспешно, то сервер переходит к следующему найденному устройству;
  2. вырабатывается ключ активации Ka;
  3. вырабатывается ключ расчета имитовставки Km для эпохи Ne = 0;
  4. для пакета проверяется совпадение имитовставки MIC на ключе Km для номера Nn = 0.

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


Детали работы процедур активации OpenUNB смотрите в первоисточнике на сайте Сколтеха.


Реализованные процедуры активации и другие процедуры безопасности доступны в исходниках здесь.


Наш бессменный мастер Интернета вещей deef137 всегда на связи и готов помочь с вопросами по коду.

Подробнее..

Чатик с открытым исходным кодом

19.02.2021 16:11:01 | Автор: admin

У меня последнее время нет времени или желания чтобы заниматься своим веб-проектом (чатик), который я разрабатывал 2 года; но очень не хочется чтобы мой труд пропадал.

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

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

Теперь о минусах

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

Если кому-то всё же интересно

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

О чем всё же речь

Сайт crawc.net (не обращайте внимания на ботов, их можно убрать). Исходный код и структуру базы данных можно скачать тут.

Более подробно почитать о сайте и его возможностях можно тут.

Подробнее..

Перевод Как классифицировать мусор с помощью Raspberry Pi и машинного обучения Arm NN

18.02.2021 20:14:00 | Автор: admin


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

Производительность таких решений сильно зависит от пропускной способности сети и задержки. Кроме того, отправка данных внешнему сервису может привести к проблемам с конфиденциальностью. В этой статье демонстрируется возможность переноса ИИ из облачной среды на периферию. Чтобы продемонстрировать ML с использованием периферийных ресурсов, мы будем использовать API-интерфейсы Arm NN для классификации изображений мусора с веб-камеры, подключённой к компьютеру Raspberry Pi, который покажет результаты классификации.



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

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



Что нам нужно для создания устройства и приложения?



  • Устройство Raspberry Pi. Урок проверен на устройствах Pi 2, Pi 3 и Pi 4 модели B.
  • Карту MicroSD.
  • Модуль камеры USB или MIPI для Raspberry Pi.
  • Чтобы создать собственную библиотеку Arm NN, также потребуется хост-компьютер Linux или компьютер с установленной виртуальной средой Linux.
  • Стекло, бумагу, картон, пластик, металл или любой другой мусор, который Raspberry Pi поможет вам классифицировать.



Конфигурация устройства


Я использовал Raspberry Pi 4 модель B с четырёхъядерным процессором ARM Cortex A72, встроенной памятью объёмом 1 ГБ, картой MicroSD объёмом 8 ГБ, аппаратным ключом WiFi и USB-камерой (Microsoft HD-3000).

Перед включением устройства необходимо установить ОС Raspbian на карту MicroSD, как описано в руководстве по настройке Raspberry Pi. Чтобы облегчить установку, я использовал установщик NOOBS.

Затем я загрузил Raspberry Pi, сконфигурировал Raspbian и настроил систему удалённого доступа к рабочему столу VNC для удалённого доступа к моему компьютеру Raspberry Pi. Подробные инструкции по настройке VNC можно найти на странице VNC (Virtual Network Computing) сайта RaspberryPi.org.

После настройки оборудования я занялся программным обеспечением. Данное решение состоит из трёх компонентов:
  • camera.hpp реализует вспомогательные методы захвата изображений с веб-камеры;
  • ml.hpp содержит методы загрузки модели машинного обучения и классификации изображений мусора на основе входных данных с камеры;
  • main.cpp содержит метод main, который объединяет указанные выше компоненты. Это точка входа в приложение.

Все эти компоненты обсуждаются ниже. Всё, что вы видите здесь, было создано с помощью редактора Geany, который по умолчанию устанавливается вместе с ОС Raspbian.

Настройка камеры


Для получения изображений с веб-камеры я использовал библиотеку OpenCV с открытым исходным кодом для компьютерного зрения. Эта библиотека предоставляет удобный интерфейс для захвата и обработки изображений. Один и тот же API-интерфейс легко использовать для различных приложений и устройств, от Интернета вещей до мобильных устройств и настольных ПК.
Самый простой способ включить OpenCV в свои приложения Raspbian для Интернета вещей установить пакет libopencv-dev с помощью программы apt-get:

sudo apt-get updatesudo apt-get upgradesudo apt-get install libopencv-dev

После загрузки и установки пакетов можно приступать к захвату изображений с веб-камеры. Я начал с реализации двух методов: grabFrame и showFrame (см. camera.hpp в сопутствующем коде):

Mat grabFrame(){  // Open default camera  VideoCapture cap(0);  // If camera was open, get the frame  Mat frame;  if (cap.isOpened())  {cap >> frame;imwrite("image.jpg", frame);   }  else  {printf("No valid camera\n");  }  return frame;} void showFrame(Mat frame){  if (!frame.empty())  {imshow("Image", frame);waitKey(0);  }}

Первый метод, grabFrame, открывает веб-камеру по умолчанию (индекс 0) и захватывает один кадр. Обратите внимание, что интерфейс C++ OpenCV для представления изображений использует класс Mat, поэтому grabFrame возвращает объекты этого типа. Доступ к необработанным данным изображения можно получить, считав элемент данных класса Mat.

Второй метод, showFrame, используется для отображения захваченного изображения. С этой целью в showFrame для создания окна, в котором отображается изображение, используется метод imshow из библиотеки OpenCV. Затем вызывается метод waitKey, чтобы окно изображения отображалось до тех пор, пока пользователь не нажмёт клавишу на клавиатуре. Время ожидания было указано с помощью параметра waitKey. Здесь использовалось бесконечное время ожидания, представленное значением 0.

Для тестирования указанных выше методов я вызвал их в методе main (main.cpp):

int main(){  // Grab image  Mat frame = grabFrame();   // Display image  showFrame(frame);   return 0;}

Для создания приложения я использовал команду g++ и связал библиотеки OpenCV посредством pkg-config:

g++ main.cpp -o trashClassifier 'pkg-config --cflags --libs opencv'

После этого я запустил приложение, чтобы захватить одно изображение:



Набор данных о мусоре и обучение модели


Модель классификации TensorFlow была обучена на основе набора данных, созданного Гэри Тунгом (Gary Thung) и доступного в его репозитории Github trashnet.

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

# Building the modelmodel = Sequential()# 3 convolutional layersmodel.add(Conv2D(32, (3, 3), input_shape = (IMG_HEIGHT, IMG_WIDTH, 3)))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Conv2D(64, (3, 3)))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Conv2D(64, (3, 3)))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Dropout(0.25))# 2 hidden layersmodel.add(Flatten())model.add(Dense(128))model.add(Activation("relu"))model.add(Dense(128))model.add(Activation("relu"))# The output layer with 6 neurons, for 6 classesmodel.add(Dense(6))model.add(Activation("softmax"))

Модель достигла точности около 83 %. С помощью преобразователя tf.lite.TFLiteConverter мы преобразовали её в формат TensorFlow Lite trash_model.tflite.

converter = tf.lite.TFLiteConverter.from_keras_model_file('model.h5') model = converter.convert()file = open('model.tflite' , 'wb') file.write(model)

Настройка пакета средств разработки Arm NN


Следующий шаг подготовка пакета средств разработки (SDK) Arm NN. При создании библиотеки Arm NN для Raspberry Pi можно последовать учебному руководству Cross-compile Arm NN and Tensorflow for the Raspberry Pi компании Arm или выполнить автоматический сценарий из репозитория Github Tool-Solutions компании Arm для кросс-компиляции пакета средств разработки. Двоичный tar-файл Arm NN 19.08 для Raspberry Pi можно найти на GitHub.

Независимо от выбранного подхода скопируйте полученный tar-файл (armnn-dist) в Raspberry Pi. В этом случае я использую VNC для передачи файлов между моим ПК для разработки и Raspberry Pi.

Затем задайте переменную среды LD_LIBRARY_PATH. Она должна указывать на подпапку armnn/lib в armnn-dist:

export LD_LIBRARY_PATH=/home/pi/armnn-dist/armnn/lib

Здесь я предполагаю, что armnn-dist находится в папке home/pi.

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


Загрузка меток вывода модели


Для интерпретации выходных данных модели необходимо использовать метки вывода модели. В нашем коде мы создаём строковый вектор для хранения 6 классов.

const std::vector<std::string> modelOutputLabels = {"cardboard", "glass", "metal", "paper", "plastic", "trash"};

Загрузка и предварительная обработка входного изображения


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

На входе нашей модели находится слой Conversion 2D (преобразование 2D) с идентификатором conv2d_input. Её выход слой активации функции Softmax с идентификатором activation_5/Softmax. Свойства модели извлекаются с помощью Tensorboard, инструмента визуализации, предоставленного в TensorFlow для проверки модели.

const std::string inputName = "conv2d_input";const std::string outputName = "activation_5/Softmax";const unsigned int inputTensorWidth = 256;const unsigned int inputTensorHeight = 192;const unsigned int inputTensorBatchSize = 32;const armnn::DataLayout inputTensorDataLayout = armnn::DataLayout::NHWC;

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

// Load and preprocess input imageconst std::vector<TContainer> inputDataContainers ={ PrepareImageTensor<uint8_t>("image.jpg" , inputTensorWidth, inputTensorHeight, normParams, inputTensorBatchSize, inputTensorDataLayout) } ;

Вся логика, связанная с загрузкой модели машинного обучения и выполнением прогнозов, содержится в файле ml.hpp.

Создание синтаксического анализатора и загрузка сети


Следующий шаг при работе с Armn NN создание объекта синтаксического анализатора, который будет использоваться для загрузки файла сети. В Arm NN есть синтаксические анализаторы для файлов моделей различных типов, включая TFLite, ONNX, Caffe и т. д. Синтаксические анализаторы обрабатывают создание базового графа Arm NN, поэтому вам не нужно создавать граф модели вручную.

В этом примере используется модель TFLite, поэтому мы создаём синтаксический анализатор TfLite для загрузки модели, используя указанный путь.

Наиболее важный метод в ml.hpp это loadModelAndPredict. Сначала он создаёт синтаксический анализатор модели TensorFlow:

// Import the TensorFlow model. // Note: use CreateNetworkFromBinaryFile for .tflite files.armnnTfLiteParser::ITfLiteParserPtr parser =   armnnTfLiteParser::ITfLiteParser::Create();armnn::INetworkPtr network =   parser->CreateNetworkFromBinaryFile("trash_model.tflite");

Затем вызывается метод armnnTfLiteParser::ITfLiteParser::Create, синтаксический анализатор используется для загрузки файла trash_model.tflite.

После анализа модели создаются привязки к слоям с помощью метода GetNetworkInputBindingInfo/GetNetworkOutputBindingInfo:

// Find the binding points for the input and output nodesconst size_t subgraphId = 0;armnnTfParser::BindingPointInfo inputBindingInfo = parser->GetNetworkInputBindingInfo(subgraphId, inputName);armnnTfParser::BindingPointInfo outputBindingInfo = parser->GetNetworkOutputBindingInfo(subgraphId, outputName);

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

// Output tensor size is equal to the number of model output labelsconst unsigned int outputNumElements = modelOutputLabels.size();std::vector<TContainer> outputDataContainers = { std::vector<uint8_t>(outputNumElements)};

Выбор внутренних интерфейсов, создание среды выполнения и оптимизация модели


Необходимо оптимизировать сеть и загрузить её на вычислительное устройство. Пакет средств разработки Arm NN поддерживает внутренние интерфейсы оптимизированного выполнения на центральных процессорах Arm, графических процессорах Mali и устройствах DSP. Внутренние интерфейсы идентифицируются строкой, которая должна быть уникальной для всех выходных интерфейсов. Можно указать один или несколько внутренних интерфейсов в порядке предпочтения.

В нашем коде Arm NN определяет, какие уровни поддерживаются внутренним интерфейсом. Сначала проверяется центральный процессор. Если один или несколько уровней невозможно выполнить на центральном процессоре, сначала осуществляется возврат к эталонной реализации.

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

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

// Optimize the network for a specific runtime compute // device, e.g. CpuAcc, GpuAccarmnn::IRuntime::CreationOptions options;armnn::IRuntimePtr runtime = armnn::IRuntime::Create(options);armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*network,   {armnn::Compute::CpuAcc, armnn::Compute::CpuRef},     runtime->GetDeviceSpec());

Механизм логического вывода в пакете Arm NN SDK предоставляет мост между существующими платформами нейронных сетей и центральными процессорами Arm Cortex-A, графическими процессорами Arm Mali и устройствами DSP. При получении логических выводов на основе машинного обучения с помощью Arm NN SDK алгоритмы машинного обучения оптимизируются для используемого оборудования.

После оптимизации сеть загружается в среду выполнения:

// Load the optimized network onto the runtime devicearmnn::NetworkId networkIdentifier;runtime->LoadNetwork(networkIdentifier, std::move(optNet));

Затем выполните прогнозы с помощью метода EnqueueWorkload:

// Predictarmnn::Status ret = runtime->EnqueueWorkload(networkIdentifier,  armnnUtils::MakeInputTensors(inputBindings, inputDataContainers),  armnnUtils::MakeOutputTensors(outputBindings, outputDataContainers));

На последнем шаге получаем результат прогнозирования.

std::vector<uint8_t> output = boost::get<std::vector<uint8_t>>(outputDataContainers[0]);size_t labelInd = std::distance(output.begin(), std::max_element(output.begin(), output.end()));std::cout << "Prediction: ";std::cout << modelOutputLabels[labelInd] << std::endl;

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

Объединение всех компонентов и создание приложения


Наконец, я собрал все компоненты вместе в методе main (main.cpp):

#include "camera.hpp"#include "ml.hpp" int main(){  // Grab frame from the camera  grabFrame(true);   // Load ML model and predict  loadModelAndPredict();   return 0;}

Обратите внимание, что у метода grabFrame есть дополнительный параметр. Если этот параметр имеет значение true, изображение камеры преобразуется в оттенки серого с изменением размеров до 256192 пикселей в соответствии с входным форматом модели машинного обучения, а затем преобразованное изображение передаётся методу loadModelAndPredict.
Для создания приложения требуется использовать команду g++ и связать библиотеку OpenCV и пакет Arm NN SDK:

g++ main.cpp -o trashClassifier 'pkg-config --cflags --libs opencv' -I/home/pi/armnn-dist/armnn/include -I/home/pi/armnn-dist/boost/include -L/home/pi/armnn-dist/armnn/lib -larmnn -lpthread -linferenceTest -lboost_system -lboost_filesystem -lboost_program_options -larmnnTfLiteParser -lprotobuf

Опять же, я предполагаю, что пакет Arm NN SDK находится в папке home/pi/armnn-dist. Запустите приложение и сделайте снимок какого-нибудь картона.

pi@raspberrypi:~/ $ ./trashClassifierArmNN v20190800Running network...Prediction: cardboard

Если во время выполнения приложения отображается сообщение error while loading shared libraries: libarmnn.so: cannot open shared object file: No such file or directory (ошибка при загрузке общих библиотек: libarmnn.so, не удаётся открыть общий объектный файл: нет такого файла или каталога), убедитесь, что ваша переменная среды LD_LIBRARY_PATH задана правильно.

Данное приложение также можно улучшить, реализовав запуск захвата и распознавания изображений по внешнему сигналу. Для этого требуется изменить метод loadAndPredict в модуле ml.hpp и отделить загрузку модели от прогнозирования (логического вывода). А если хотите прокачать себя в Data Science, Machine Learning или поднять уровень уже имеющихся знаний приходите учиться, будет сложно, но интересно.

image
Узнайте подробности, как получить Level Up по навыкам и зарплате или востребованную профессию с нуля, пройдя онлайн-курсы SkillFactory со скидкой 40% и промокодом HABR, который даст еще +10% скидки на обучение:

Подробнее..

Приглашаю к созданию русской народной игры Колобок

21.02.2021 16:09:36 | Автор: admin

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


Почему Колобок


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


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


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


Как я готоволю Колобка


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


Т.к. всё, что видно на экране, является спрайтом (изображением), то желаемый элемент игры я:


  • сначала рисую на обычном листе бумаги
  • фотографирую нарисованные каракули на телефон
  • обрезаю изображение в GIMP
  • сохраняю изображение в PNG
  • создаю в GDevelop новый спрайт на основе изображения PNG

Самым сложным элементом на текущий момент являлся кот, т.к. мне нужно было несколько состояний кота:


  • сидит без эмоций;
  • сидит недовольный;
  • спрыгивает с подоконника;
  • лижет пролитое молоко.

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




Ближе к делу


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


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


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


Если у вас зачесались руки, то добро пожаловать в уютную группу Discord.


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

Подробнее..

НАСА в марсолете Ingenuity используется открытое ПО и Linux

22.02.2021 14:21:33 | Автор: admin

Агентство НАСА на днях раскрыло подробности работы марсолета Ingenuity, который опустился на поверхность Красной планеты вместе с марсоходом. Вскоре марсолет попробует освоить воздушное пространство Марса, а пока что НАСА рассказывает о подробностях этого путешествия.

Так вот, железо марсолета базируется на плате с SoC Snapdragon 801 от компании Qualcomm. Программное обеспечение Linux и открытое ПО. По словам агентства, программное обеспечение на основе Linux впервые используется в системах, отправленных на Марс. Использование же открытых и доступных элементов, как железа, так и ПО, дает возможность энтузиастам повторить конструкцию или сделать нечто свое.



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

SoC Snapdragon 801 (четыре ядра, 2.26 GHz, 2 ГБ ОЗУ, 32 ГБ Flash) отвечает за работу базового системного окружения на базе Linux. Именно оно выполняет высокоуровневые операции, включая:

Визуальную навигацию на основе анализа изображений с камеры.
Управление данными.
Обработка команд.
Формирование телеметрии.
Поддержание канала беспроводной связи.

Посредством интерфейса UART процессор соединяется с двумя микроконтроллерами, это MCU Texas Instruments TMS570LC43x, ARM Cortex-R5F, 300 MHz, 512 КБ ОЗУ, 4 МБ Flash, UART, SPI, GPIO. Они отвечают для различных функций управления полета. Кроме того, они же используются для резервирования на случай сбоя, так что информация, которая к ним поступает, дублируется.


Задействуется лишь один из микроконтроллеров, но если что-то идет не так, то вступает в работу второй, который способен сразу же перехватить основные функции, заменив проблемного коллегу. Ну а за передачу информации от датчиков к микроконтроллеров, а также за взаимодействие с актуаторами, которые управляют лопастями винтокрылого летуна, отвечает FPGA MicroSemi ProASIC3L. Он же выполняет переключение на запасной микроконтроллер в случае сбоя.


В предыдущей нашей статье говорилось, что научного оборудования в этом устройстве нет. Но, конечно, это не просто летающая болванка. Марсолет оснащен лазерным высотомером от компании SparkFun Electronics. Она специализируется на разработке открытого ПО, кроме того, она же и один из создателей самого термина OSHW, Open-source hardware. Кроме того, марсолет оснащен такими компонентами, как гиростабилизатор (IMU) и видеокамеры.

Камер две. Одна из них, VGA, используется в качестве навигационной, отвечает за определение местоположения, направления движения и скорости посредством покадрового сравнения. А вот вторая камера, цветная, 13 МП, будет использоваться для фотографирования местности. Аэрофотосъемка на Марсе мы живем в будущем!

Большая часть систем марсолета разработана специалистами НАСА, а именно в лаборатории NASA JPL (Jet Propulsion Laboratory). При этом компоненты, которые применены в конструкции, не уникальные, а типовые, они созданы специально для малых и сверхмалых искусственных спутников Земли (кубсатов) и уже несколько лет развиваются в составе открытой платформы F Prime (F), распространяемой под лицензией Apache 2.0.


F Prime дает возможность быстро разрабатывать и разворачивать системы управления полетом и связанных элементов ПО. При этом полетное ПО разделяется на отдельные компоненты с хорошо определенными программными интерфейсами. Кроме того, разработчики получают в свое распоряжение С++ фреймворк для обработки очередей сообщений, организации многопоточности, плюс инструменты моделирования, которые позволяют связывать компоненты и автоматически генерировать код.

Подробнее..

Учим HostBinding работать с Observable

26.02.2021 18:20:16 | Автор: admin

Как и многие другие Angular-разработчики, я мирился с одним ограничением. Если мы хотим использовать Observable в шаблоне, мы можем взять знакомый всем async пайп:

<button [disabled]=isLoading$ | async>

Но его нельзя применить к @HostBinding. Давным-давно это было возможно по ошибке, но это быстро исправили:

@Directive({  selector: 'button[my-button]'  host: {    '[disabled]': '(isLoading$ | async)'  }})export class MyButtonDirective {

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

Как работает асинхронный байндинг?

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

Зачем это может понадобиться?

Мы часто работаем с RxJS в Angular. Большинство наших сервисов построены на Observable-модели. Вот пара примеров, где возможность завязываться на реактивные данные в @HostBinding была бы полезна:

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

  • Изменение класса или стилей. Observable-сервис может управлять размером или трансформацией через изменение стилей хоста. Или, например, мы можем использовать реактивный IntersectionObserver для применения класса к sticky-шапке в таблице:

  • Изменение полей и атрибутов. Иногда мы хотим завязаться на BreakpointObserver для обновления placeholder или на сервис загрузки данных для выставления disable на кнопке.

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

В Taiga UI библиотеке, над которой я работаю, есть несколько инструментов, чтобы сделать этот процесс максимально декларативным:

import {TuiDestroyService, watch} from '@taiga-ui/cdk';import {Language, TUI_LANGUAGE} from '@taiga-ui/i18n';import {Observable} from 'rxjs';import {map, takeUntil} from 'rxjs/operators';@Component({   selector: 'my-comp',   template: '',   providers: [TuiDestroyService],})export class MyComponent {   @HostBinding('attr.aria-label')   label = '';   constructor(       @Inject(TUI_LANGUAGE) language$: Observable<Language>,       @Inject(TuiDestroyService) destroy$: Observable<void>,       @Inject(ChangeDetectorRef) changeDetectorRef: ChangeDetectorRef,   ) {       language$.pipe(           map(getTranslation('label')),           watch(changeDetectorRef),           takeUntil(destroy$),       ).subscribe();   }}

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

@HostBinding('attr.aria-label')readonly label$ = this.translations.get$('label');

Это потребует серьезных доработок со стороны команды Angular. Но мы можем использовать хитрый трюк в рамках публичного API, чтобы заставить это работать!

Event-плагины спешат на помощь!

Мы не можем добавить свою логику к байндингу на хост. Но мы можем сделать это для @HostListener! Я уже писал статью на эту тему. Прочитайте ее, если хотите узнать, как добавить декларативные preventDefault/stopPropagation и оптимизировать циклы проверки изменений. Если кратко Angular позволяет добавлять свои сервисы для обработки событий. Подходящий сервис выбирается с помощью имени события. Давайте перепишем код следующим образом:

@HostBinding('$.aria-label.attr')@HostListener('$.aria-label.attr')readonly label$ = this.translations.get$('label');

Выглядит странно пытаться решить задачу @HostBinding через @HostListener но читайте дальше и вы всё увидите.

Мы будем использовать $ в качестве индикатора в имени события. Модификатор .attr добавим в конец, а не в начало. Иначе регулярное выражение в Angular решит, что мы байндим строковый атрибут.

У плагинов для обработки событий есть доступ к элементу, имени события и функции-обработчику. Последний аргумент для нас бесполезен, так как это обертка, созданная компилятором. Так что нам нужно как-то передать наш Observable через элемент. Вот тут-то нам и пригодится @HostBinding. Мы положим Observable в поле с тем же именем, и тогда у нас будет доступ к нему внутри плагина:

addEventListener(element: HTMLElement, event: string): Function {   element[event] = EMPTY;   const method = this.getMethod(element, event);   const sub = this.manager       .getZone()       .onStable.pipe(           take(1),           switchMap(() => element[event]),       )       .subscribe(method);   return () => sub.unsubscribe();}

Компилятор Angular

Посмотрим на этот код повнимательнее. Первая строка может вас смутить. Хоть мы и можем назначать произвольные поля на элементы, Angular попытается их провалидировать:

Возможно, вы видели такое раньшеВозможно, вы видели такое раньше

Плагины хороши тем, что подписка на события происходит раньше разрешения байндингов. Благодаря первой строке Angular считает, что у элемента присутствует это свойство. Дальше нам нужно убедиться, что Observable уже на месте ведь на момент подписки его еще нет. Хорошо, что у нас есть доступ до NgZone и мы можем дождаться ее стабилизации, прежде чем запросить свойство элемента.

NgZone испускает onStable когда не осталось больше микро- и макрозадач в очереди. Для нас это означает, что Angular завершил цикл проверки изменений и все байндинги обновлены.

А отписку за нас сделает сам Angular достаточно вернуть функцию, прерывающую стрим.

Этого хватит, чтобы код заработал в JIT, AOT же более щепетилен. Мы добавили несуществующее поле во время выполнения, но AOT желает знать про него на этапе компиляции. До тех пор, пока эта задача не будет закрыта, мы не можем создавать свои списки разрешенных полей. Поэтому нам придется добавить NO_ERRORS_SCHEMA в модуль с подобным байндингом. Это может звучать страшно, но все, что эта схема делает, перестает проверять, есть ли поле у элемента при байндинге. Кроме того, если у вас WebStorm, вы продолжите видеть предупреждение:

Это сообщение не мешает сборкеЭто сообщение не мешает сборке

Также AOT требует реализации Callable-интерфейса для использования @HostListener. Мы можем имитировать его с помощью простой функции, сохранив оригинальный тип:

function asCallable<T>(a: T): T & Function {    return a as any;}

Итоговая запись:

@HostBinding('$.aria-label.attr')@HostListener('$.aria-label.attr')readonly label$ = asCallable(this.translations.get$('label'));

Другой вариант вовсе отказаться от @HostBinding ведь нам надо назначить его лишь один раз. Если ваш стрим приходит из DI, что происходит довольно часто, можно создать FactoryProvider. В него можно передать ElementRef и назначить поле в нем:

export const TOKEN = new InjectionToken<Observable<boolean>>("");export const PROVIDER = {  provide: TOKEN,  deps: [ElementRef, IntersectionObserverService],  useFactory: factory,}export function factory(  { nativeElement }: ElementRef,  entries$: Observable<IntersectionObserverEntry[]>): Observable<boolean> {  return nativeElement["$.class.stuck"] = entries$.pipe(map(isIntersecting));}

Теперь достаточно будет оставить только @HostListener. Его даже можно написать прямо в декораторе класса:

@Directive({  selector: "table[sticky]",  providers: [    IntersectionObserverService,    PROVIDER,  ],  host: {    "($.class.stuck)": "stuck$"  }})export class StickyDirective {  constructor(@Inject(TOKEN) readonly stuck$: Observable<boolean>) {}}

Приведенный выше пример можно увидеть вживую на StackBlitz. В нем IntersectionObserver используется для задания тени на sticky-шапке таблицы:

Обновление полей

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

private getMethod(element: HTMLElement, event: string): Function {   const [, key, value, unit = ''] = event.split('.');   if (event.endsWith('.attr')) {       return v => element.setAttribute(key, String(v));   }   if (key === 'class') {       return v => element.classList.toggle(value, !!v);   }   if (key === 'style') {       return v => element.style.setProperty(value, `${v}${unit}`);   }   return v => (element[key] = v);}

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

{    provide: EVENT_MANAGER_PLUGINS,    useClass: BindEventPlugin,    multi: true,}

Это небольшое дополнение способно существенно упростить ваш код. Нам больше не надо беспокоиться о подписке. Описанный плагин доступен в новой версии 2.1.1 нашей библиотеки @tinkoff/ng-event-plugins, а также в @taiga-ui/cdk. Поиграться с кодом можно на StackBlitz. Надеюсь, этот материал будет для вас полезным!

Подробнее..

Рефакторинг пет проекта докеризация, метрики, тесты

17.02.2021 20:19:33 | Автор: admin

Всем привет, я php разработчик. Я хочу поделиться историей, как я рефакторил один из своих телеграм ботов, который из поделки на коленке стал сервисом с более чем 1000 пользователей в очень узкой и специфической аудитории.

Предыстория

Пару лет назад я решил тряхнуть стариной и поиграть в LineAge II на одном из популярных пиратских серверов. В этой игре есть один игровой процесс, в котором требуется "поговорить" с ящиками после смерти 4 боссов. Ящик стоит после смерти 2 минуты. Сами боссы после смерти появляются спустя 24 +/- 6ч, то есть шанс появится есть как через 18ч, так и через 30ч. У меня на тот момент была фуллтайм работа, да и в целом не было времени ждать эти ящики. Но нескольким моим персонажам требовалось пройти этот квест, поэтому я решил "автоматизировать" этот процесс. На сайте сервера есть RSS фид в формет XML, где публикуются события с серверов, включая события смерти босса.

Задумка была следующей:

  • получить данные с RSS

  • сравнить данные с локальной копией в базе данных

  • если есть разница данных - сообщить об этом в телеграм канал

  • отдельно сообщать если босса не убили за первые 9ч сообщением "осталось 3ч", и "осталось 1,5ч". Допустим вечером пришло сообщение, что осталось 3ч, значит смерть босса будет до того, как я пойду спать.

Код на php был написан быстро и в итоге у меня было 3 php файла. Один был с god object классом, а другие два запускали программу в двух режимах - парсер новых, или проверка есть ли боссы на максимальном "респе". Запускал я их крон командами. Это работало и решало мою проблему.

Другие игроки замечали, что я появляюсь в игре сразу после смерти боссов, и через 10 дней у меня на канале было около 50 подписчиков. Так же попросили сделать такое же для второго сервера этого пиратского сервиса. Задачу я тоже решил копипастой. В итоге у меня уже 4 файла с почти одинаковым кодом, и файл с god object. Потом меня попросили сделать то же самое для третьего сервера этого пиратского сервиса. И это отлично работало полтора года.

В итоге у меня спустя полтора года:

  • у меня 6 файлов, дублируют себя почти полностью (по 2 файла на сервер)

  • один god object на несколько сотен строк

  • MySQL и Redis на сервере, где разместил код

  • cron задачи, которые запускают файлы

  • ~1400 подписчиков на канале в телеграм

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

Ожидаемый результат после рефакторинга

  1. Отрефакторить код так, чтобы легче было вносить изменения. Важный момент - отрефакторить без изменения бизнес логики, по сути раскидать god object по файлам, сам код не править, иначе это затянет сроки. Следовать PSR-12.

  2. Докеризировать воркера для удобства переноса на другой сервер и прозрачность запуска и остановки

  3. Запускать воркера через supervisor

  4. Внедрить процесс тестирования кода, настроить Codeception

  5. Докеризировать MySQL и Redis

  6. Настроить Github Actions для запуска тестов и проверки на code style

  7. Поднять Prometheus, Grafana для метрик и мониторинга работоспособности

  8. Сделать докер контейнер, который будет отдавать метрики на страницу /metrics для Prometheus

  9. Сделать докер образ для бота телеграм, который будет отдавать срез по всем статусам 4 боссов в данный момент командами боту в личку

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

Шаг 1. Рефакторинг приложения

Одним из требований было не потратить на это недели, поэтому основные классы я решил сделать наследниками Singleton

<?phpdeclare(strict_types=1);namespace AsteriosBot\Core\Support;use AsteriosBot\Core\Exception\DeserializeException;use AsteriosBot\Core\Exception\SerializeException;class Singleton{    protected static $instances = [];    /**     * Singleton constructor.     */    protected function __construct()    {        // do nothing    }    /**     * Disable clone object.     */    protected function __clone()    {        // do nothing    }    /**     * Disable serialize object.     *     * @throws SerializeException     */    public function __sleep()    {        throw new SerializeException("Cannot serialize singleton");    }    /**     * Disable deserialize object.     *     * @throws DeserializeException     */    public function __wakeup()    {        throw new DeserializeException("Cannot deserialize singleton");    }    /**     * @return static     */    public static function getInstance(): Singleton    {        $subclass = static::class;        if (!isset(self::$instances[$subclass])) {            self::$instances[$subclass] = new static();        }        return self::$instances[$subclass];    }}

Таким образом вызов любого класса, который от него наследуются, можно делать методом getInstance()

Вот так, например, выглядел класс подключения к базе данных

<?phpdeclare(strict_types=1);namespace AsteriosBot\Core\Connection;use AsteriosBot\Core\App;use AsteriosBot\Core\Support\Config;use AsteriosBot\Core\Support\Singleton;use FaaPz\PDO\Database as DB;class Database extends Singleton{    /**     * @var DB     */    protected DB $connection;    /**     * @var Config     */    protected Config $config;    /**     * Database constructor.     */    protected function __construct()    {        $this->config = App::getInstance()->getConfig();        $dto = $this->config->getDatabaseDTO();        $this->connection = new DB($dto->getDsn(), $dto->getUser(), $dto->getPassword());    }    /**     * @return DB     */    public function getConnection(): DB    {        return $this->connection;    }}

В процессе рефакторинга я не менял саму бизнес логику, оставил все "как было". Цель было именно разнести по файлам для облегчения изменения правок, а так же для возможности потом покрыть тестами.

Шаг 2: Докеризация воркеров

Запуск всех контейнеров я сделал через docker-compose.yml

Конфиг сервиса для воркеров выглядит так:

  worker:    build:      context: .      dockerfile: docker/worker/Dockerfile    container_name: 'asterios-bot-worker'    restart: always    volumes:      - .:/app/    networks:      - tier

А сам docker/worker/Dockerfile выглядит так:

FROM php:7.4.3-alpine3.11# Copy the application codeCOPY . /appRUN apk update && apk add --no-cache \    build-base shadow vim curl supervisor \    php7 \    php7-fpm \    php7-common \    php7-pdo \    php7-pdo_mysql \    php7-mysqli \    php7-mcrypt \    php7-mbstring \    php7-xml \    php7-simplexml \    php7-openssl \    php7-json \    php7-phar \    php7-zip \    php7-gd \    php7-dom \    php7-session \    php7-zlib \    php7-redis \    php7-session# Add and Enable PHP-PDO ExtenstionsRUN docker-php-ext-install pdo pdo_mysqlRUN docker-php-ext-enable pdo_mysql# RedisRUN apk add --no-cache pcre-dev $PHPIZE_DEPS \        && pecl install redis \        && docker-php-ext-enable redis.so# Install PHP ComposerRUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer# Remove CacheRUN rm -rf /var/cache/apk/*# setup supervisorADD docker/supervisor/asterios.conf /etc/supervisor/conf.d/asterios.confADD docker/supervisor/supervisord.conf /etc/supervisord.confVOLUME ["/app"]WORKDIR /appRUN composer installCMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

Обратите внимание на последнюю строку в Dockerfile, там я запускаю supervisord, который будет мониторить работу воркеров.

Шаг 3: Настройка supervisor

Важный дисклеймер по supervisor. Он предназначен для работы с процессами, которые работают долго, и в случае его "падения" - перезапустить. Мои же php скрипты работали быстро и сразу завершались. supervisor пробовал их перезапустить, и в конце концов переставал пытаться поднять снова. Поэтому я решил сам код воркера запускать на 1 минуту, чтобы это работало с supervisor.

Код файла worker.php

<?phprequire __DIR__ . '/vendor/autoload.php';use AsteriosBot\Channel\Checker;use AsteriosBot\Channel\Parser;use AsteriosBot\Core\App;use AsteriosBot\Core\Connection\Log;$app = App::getInstance();$checker = new Checker();$parser = new Parser();$servers = $app->getConfig()->getEnableServers();$logger = Log::getInstance()->getLogger();$expectedTime = time() + 60; // +1 min in seconds$oneSecond = time();while (true) {    $now = time();    if ($now >= $oneSecond) {        $oneSecond = $now + 1;        try {            foreach ($servers as $server) {                $parser->execute($server);                $checker->execute($server);            }        } catch (\Throwable $e) {            $logger->error($e->getMessage(), $e->getTrace());        }    }    if ($expectedTime < $now) {        die(0);    }}

У RSS есть защита от спама, поэтому пришлось сделать проверку на секунды и посылать не более 1го запроса в секунду. Таким образом мой воркер каждую секунду выполняет 2 действия, сначала проверяет rss, а затем калькулирует время боссов для сообщений о старте или окончании времени респауна боссов. После 1 минуты работы воркер умирает, и его перезапускает supervisor

Сам конфиг supervisor выглядит так:

[program:worker]command = php /app/worker.phpstderr_logfile=/app/logs/supervisor/worker.lognumprocs = 1user = rootstartsecs = 3startretries = 10exitcodes = 0,2stopsignal = SIGINTreloadsignal = SIGHUPstopwaitsecs = 10autostart = trueautorestart = truestdout_logfile = /dev/stdoutstdout_logfile_maxbytes = 0redirect_stderr = true

После старта контейнеров супервизор стартует воркера автоматически. Важный момент - в файле основного конфига /etc/supervisord.confобязательно нужно указать демонизация процесса, а так же подключение своих конфигов

[supervisord]nodaemon=true[include]files = /etc/supervisor/conf.d/*.conf

Набор полезных команд supervisorctl:

supervisorctl status       # статус воркеровsupervisorctl stop all     # остановить все воркераsupervisorctl start all    # запустить все воркераsupervisorctl start worker # запустить один воркера с конфига, блок [program:worker]

Шаг 4: Настройка Codeception

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

# Codeception Test Suite Configuration## Suite for unit or integration tests.actor: UnitTestermodules:    enabled:        - Asserts        - \Helper\Unit        - Db:              dsn: 'mysql:host=mysql;port=3306;dbname=test_db;'              user: 'root'              password: 'password'              dump: 'tests/_data/dump.sql'              populate: true              cleanup: true              reconnect: true              waitlock: 10              initial_queries:                - 'CREATE DATABASE IF NOT EXISTS test_db;'                - 'USE test_db;'                - 'SET NAMES utf8;'    step_decorators: ~

Шаг 5: Докеризация MySQL и Redis

На сервере, где работало это приложение, у меня было еще пара других ботов. Все они использовали один сервер MySQL и один Redis для кеша. Я решил вынести все, что связано с окружением в отельный docker-compose.yml, а самих ботов залинковать через внешний docker network

Выглядит это так:

version: '3'services:  mysql:    image: mysql:5.7.22    container_name: 'telegram-bots-mysql'    restart: always    ports:      - "3306:3306"    environment:      MYSQL_ROOT_PASSWORD: "${DB_PASSWORD}"      MYSQL_ROOT_HOST: '%'    volumes:      - ./docker/sql/dump.sql:/docker-entrypoint-initdb.d/dump.sql    networks:      - tier  redis:    container_name: 'telegram-bots-redis'    image: redis:3.2    restart: always    ports:      - "127.0.0.1:6379:6379/tcp"    networks:      - tier  pma:    image: phpmyadmin/phpmyadmin    container_name: 'telegram-bots-pma'    environment:      PMA_HOST: mysql      PMA_PORT: 3306      MYSQL_ROOT_PASSWORD: "${DB_PASSWORD}"    ports:      - '8006:80'    networks:      - tiernetworks:  tier:    external:      name: telegram-bots-network

DB_PASSWORD я храню в .env файле, а ./docker/sql/dump.sql у меня лежит бекап для инициализации базы данных. Так же я добавил external network так же, как в этом конфиге - в каждом docker-compose.yml каждого бота на сервере. Таким образом они все находятся в одной сети и могут использовать общие базу данных и редис.

Шаг 6: Настройка Github Actions

В шаге 4 этого туториала я добавил тестовый фреймфорк Codeception, который для тестирования требует базу данных. В самом проекте нет базы, в шаге 5 я ее вынес отдельно и залинковал через external docker network. Для запуска тестов в Github Actions я решил полностью собрать все необходимое на лету так же через docker-compose.

name: Actionson:  pull_request:    branches: [master]  push:    branches: [master]jobs:  build:    runs-on: ubuntu-latest    steps:      - name: Checkout        uses: actions/checkout@v2      - name: Get Composer Cache Directory        id: composer-cache        run: |          echo "::set-output name=dir::$(composer config cache-files-dir)"      - uses: actions/cache@v1        with:          path: ${{ steps.composer-cache.outputs.dir }}          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}          restore-keys: |            ${{ runner.os }}-composer-      - name: Composer validate        run: composer validate      - name: Composer Install        run: composer install --dev --no-interaction --no-ansi --prefer-dist --no-suggest --ignore-platform-reqs      - name: PHPCS check        run: php vendor/bin/phpcs --standard=psr12 app/ -n      - name: Create env file        run: |          cp .env.github.actions .env      - name: Build the docker-compose stack        run: docker-compose -f docker-compose.github.actions.yml -p asterios-tests up -d      - name: Sleep        uses: jakejarvis/wait-action@master        with:          time: '30s'      - name: Run test suite        run: docker-compose -f docker-compose.github.actions.yml -p asterios-tests exec -T php vendor/bin/codecept run unit

Инструкция onуправляет когда билд триггернётся. В моем случае - при создании пулл реквеста или при коммите в мастер.

Инструкция uses: actions/checkout@v2 запускает проверку доступа процесса к репозиторию.

Далее идет проверка кеша композера, и установка пакетов, если в кеше не найдено

Затем в строке run: php vendor/bin/phpcs --standard=psr12 app/ -nя запускаю проверку кода соответствию стандарту PSR-12 в папке ./app

Так как тут у меня специфическое окружение, я подготовил файл .env.github.actionsкоторый копируется в .env Cодержимое .env.github.actions

SERVICE_ROLE=testTG_API=XXXXXTG_ADMIN_ID=123TG_NAME=AsteriosRBbotDB_HOST=mysqlDB_NAME=rootDB_PORT=3306DB_CHARSET=utf8DB_USERNAME=rootDB_PASSWORD=passwordLOG_PATH=./logs/DB_NAME_TEST=test_dbREDIS_HOST=redisREDIS_PORT=6379REDIS_DB=0SILENT_MODE=trueFILLER_MODE=true

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

Затем я собираю проект при помощи docker-compose.github.actions.ymlв котором прописано все необходимое для тестирвания, контейнер с проектом и база данных. Содержимое docker-compose.github.actions.yml:

version: '3'services:  php:    build:      context: .      dockerfile: docker/php/Dockerfile    container_name: 'asterios-tests-php'    volumes:      - .:/app/    networks:      - asterios-tests-network  mysql:    image: mysql:5.7.22    container_name: 'asterios-tests-mysql'    restart: always    ports:      - "3306:3306"    environment:      MYSQL_DATABASE: asterios      MYSQL_ROOT_PASSWORD: password    volumes:      - ./tests/_data/dump.sql:/docker-entrypoint-initdb.d/dump.sql    networks:      - asterios-tests-network##  redis:#    container_name: 'asterios-tests-redis'#    image: redis:3.2#    ports:#      - "127.0.0.1:6379:6379/tcp"#    networks:#      - asterios-tests-networknetworks:  asterios-tests-network:    driver: bridge

Я закомментировал контейнер с Redis, но оставил возможность использовать его в будущем. Сборка с кастомным docker-compose файлом, а затем тесты - запускается так

docker-compose -f docker-compose.github.actions.yml -p asterios-tests up -ddocker-compose -f docker-compose.github.actions.yml -p asterios-tests exec -T php vendor/bin/codecept run unit

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

Шаг 7: Настройка Prometheus и Grafana

В шаге 5 я вынес MySQL и Redis в отдельный docker-compose.yml. Так как Prometheus и Grafana тоже общие для всех моих телеграм ботов, я их добавил туда же. Сам конфиг этих контейнеров выглядит так:

  prometheus:    image: prom/prometheus:v2.0.0    command:      - '--config.file=/etc/prometheus/prometheus.yml'    restart: always    ports:      - 9090:9090    volumes:      - ./prometheus.yml:/etc/prometheus/prometheus.yml    networks:      - tier  grafana:    container_name: 'telegram-bots-grafana'    image: grafana/grafana:7.1.1    ports:      - 3000:3000    environment:      - GF_RENDERING_SERVER_URL=http://renderer:8081/render      - GF_RENDERING_CALLBACK_URL=http://grafana:3000/      - GF_LOG_FILTERS=rendering:debug    volumes:      - ./grafana.ini:/etc/grafana/grafana.ini      - grafanadata:/var/lib/grafana    networks:      - tier    restart: always  renderer:    image: grafana/grafana-image-renderer:latest    container_name: 'telegram-bots-grafana-renderer'    restart: always    ports:      - 8081    networks:      - tier

Они так же залинкованы одной сетью, которая потом линкуется с external docker network.

Prometheus: я прокидываю свой конфиг prometheus.yml, где я могу указать источники для парсинга метрик

Grafana: я создаю volume, где будут храниться конфиги и установленные плагины. Так же я прокидываю ссылку на сервис рендеринга графиков, который мне понадобиться для отправки alert. С этим плагином alert приходит со скриншотом графика.

Поднимаю проект и устанавливаю плагин, затем перезапускаю Grafana контейнер

docker-compose up -ddocker-compose exec grafana grafana-cli plugins install grafana-image-rendererdocker-compose stop  grafana docker-compose up -d grafana

Шаг 8: Публикация метрик приложения

Для сбора и публикации метрик я использовал endclothing/prometheus_client_php

Так выглядит мой класс для метрик

<?phpdeclare(strict_types=1);namespace AsteriosBot\Core\Connection;use AsteriosBot\Core\App;use AsteriosBot\Core\Support\Singleton;use Prometheus\CollectorRegistry;use Prometheus\Exception\MetricsRegistrationException;use Prometheus\Storage\Redis;class Metrics extends Singleton{    private const METRIC_HEALTH_CHECK_PREFIX = 'healthcheck_';    /**     * @var CollectorRegistry     */    private $registry;    protected function __construct()    {        $dto = App::getInstance()->getConfig()->getRedisDTO();        Redis::setDefaultOptions(            [                'host' => $dto->getHost(),                'port' => $dto->getPort(),                'database' => $dto->getDatabase(),                'password' => null,                'timeout' => 0.1, // in seconds                'read_timeout' => '10', // in seconds                'persistent_connections' => false            ]        );        $this->registry = CollectorRegistry::getDefault();    }    /**     * @return CollectorRegistry     */    public function getRegistry(): CollectorRegistry    {        return $this->registry;    }    /**     * @param string $metricName     *     * @throws MetricsRegistrationException     */    public function increaseMetric(string $metricName): void    {        $counter = $this->registry->getOrRegisterCounter('asterios_bot', $metricName, 'it increases');        $counter->incBy(1, []);    }    /**     * @param string $serverName     *     * @throws MetricsRegistrationException     */    public function increaseHealthCheck(string $serverName): void    {        $prefix = App::getInstance()->getConfig()->isTestServer() ? 'test_' : '';        $this->increaseMetric($prefix . self::METRIC_HEALTH_CHECK_PREFIX . $serverName);    }}

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

        if ($counter) {            $this->metrics->increaseHealthCheck($serverName);        }

Где переменная $counter это количество записей в RSS. Там будет 0, если получить данные не удалось, и значит метрика не будет сохранена. Это потом понадобится для alert по работе сервиса.

Затем нужно метрики опубликовать на странице /metric чтобы Prometheus их спарсил. Добавим хост в конфиг prometheus.yml из шага 7.

# my global configglobal:  scrape_interval:     5s # Set the scrape interval to every 15 seconds. Default is every 1 minute.  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.  # scrape_timeout is set to the global default (10s).scrape_configs:  - job_name: 'bots-env'    static_configs:      - targets:          - prometheus:9090          - pushgateway:9091          - grafana:3000          - metrics:80 # тут будут мои метрики по uri /metrics

Код, который вытащит метрики из Redis и создаст страницу в текстовом формате. Эту страничку будет парсить Prometheus

$metrics = Metrics::getInstance();$renderer = new RenderTextFormat();$result = $renderer->render($metrics->getRegistry()->getMetricFamilySamples());header('Content-type: ' . RenderTextFormat::MIME_TYPE);echo $result;

Теперь настроим сам дашборд и alert. В настройках Grafana сначала укажите свой Prometheus как основной источник данных, а так же я добавил основной канал нотификации Телеграм (там добавляете токен своего бота и свой chat_id с этим ботом)

Настройка GrafanaНастройка Grafana
  1. Метрика increase(asterios_bot_healthcheck_x3[1m]) Показывает на сколько метрика asterios_bot_healthcheck_x3 увеличилась за 1 минуту

  2. Название метрики (будет под графиком)

  3. Название для легенды в пункте 4.

  4. Легенда справа из пункта 3.

  1. Правило, по которому проверяется метрика. В моем случае проверяет что за последние 30 секунд проблем не было

  2. Правило, по которому будет срабатывать alert. В моем случае "Когда сумма из метрики А между сейчас и 10 секунд назад"

  3. Если нет данных вообще - слать alert

  4. Сообщение в alert

Выглядит alert в телеграм так (помните мы настраивали рендеринг картинок для alert?)

Alert в ТелеграмAlert в Телеграм
  1. Обратите внимание, alert заметил падение, но все восстановилось. Grafana приготовилась слать alert, но передумала. Это то самое правило 30 секунд

  2. Тут уже все упало больше чем на 30 секунд и alert был отправлен

  3. Сообщение, которое мы указали в настройках alert

  4. Ссылка на dashboard

  5. Источник метрики

Шаг 9: Телеграм бот

Настройка телеграм бота ничем не отличается от настройки воркера. Телеграм бот по сути у меня это еще один воркер, я запустил его при помощи добавления настроек в supervisor. Тут уже рефакторинг проекта дал свои плоды, запуск бота был быстрым и простым.

Итоги

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

Ссылки на проекты

Подробнее..

Зачем PVS-Studio использует анализ потока данных по мотивам интересной ошибки в Open Asset Import Library

18.02.2021 18:15:13 | Автор: admin

PVS-Studio - Анализ потока данных
Анализ потока данных является неотъемлемой частью любого современного статического анализатора кода. Однако, со стороны, не очень понятно, что это и главное зачем нужно. До сих пор некоторые ассоциируют статический анализ с поиском чего-то в коде по определённому шаблону. Поэтому время от времени мы пишем заметки, в которых демонстрируем, как та или иная технология, используемая в анализаторе PVS-Studio, помогает выявить очередную интересную ошибку. Сегодня как раз такая статья, в которой мы рассмотрим баг в одной из реализаций стандарта кодирования двоичных данных Base64.


Всё началось с проверки свежей версии библиотеки Qt 6. Про это была отдельная классическая статья, где я описал 77 найденных ошибок. Так получилось, что вначале я решил бегло полистать отчёт, ещё не пряча предупреждения, относящиеся к сторонним библиотекам. Другими словами, я не отключил в настройках предупреждения, относящиеся к \src\3rdparty. И так вышло, что я сразу наткнулся на интересный пример ошибки в библиотеки Open Asset Import Library, про которую я решил сделать эту отдельную маленькую заметку.


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


Теперь перейдём, собственно, к ошибке, обнаруженной в Open Asset Import Library (assimp). Файл: \src\3rdparty\assimp\src\code\FBX\FBXUtil.cpp.


std::string EncodeBase64(const char* data, size_t length){    // calculate extra bytes needed to get a multiple of 3    size_t extraBytes = 3 - length % 3;    // number of base64 bytes    size_t encodedBytes = 4 * (length + extraBytes) / 3;    std::string encoded_string(encodedBytes, '=');    // read blocks of 3 bytes    for (size_t ib3 = 0; ib3 < length / 3; ib3++)    {        const size_t iByte = ib3 * 3;        const size_t iEncodedByte = ib3 * 4;        const char* currData = &data[iByte];        EncodeByteBlock(currData, encoded_string, iEncodedByte);    }    // if size of data is not a multiple of 3,    // also encode the final bytes (and add zeros where needed)    if (extraBytes > 0)    {        char finalBytes[4] = { 0,0,0,0 };        memcpy(&finalBytes[0], &data[length - length % 3], length % 3);        const size_t iEncodedByte = encodedBytes - 4;        EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte);        // add '=' at the end        for (size_t i = 0; i < 4 * extraBytes / 3; i++)            encoded_string[encodedBytes - i - 1] = '=';    }    return encoded_string;}

Если хотите, то для начала можете попробовать обнаружить ошибку самостоятельно. А чтобы вы случайно сразу не прочитали ответ, приведу пока список некоторых других интересных статей и кратко расскажу, что такое Base64 :). Список дополнительных статей на близкую тематику:


  1. 31 февраля;
  2. Использование машинного обучения в статическом анализе исходного кода программ;
  3. Как внедрить статический анализатор кода в legacy проект и не демотивировать команду.

Ok, продолжим. Перед нами реализация алгоритма кодирования строки байт в кодировку Base64. Это стандарт кодирования двоичных данных при помощи только 64 символов. Алфавит кодирования содержит текстово-цифровые латинские символы A-Z, a-z и 0-9 (62 знака) и 2 дополнительных символа, зависящих от системы реализации. Каждые 3 исходных байта кодируются 4 символами.


Если осталось закодировать только один или два байта, то в результате получаются только первые два или три символа строки, а выходная строка дополняется двумя или одним символами "=". Это предотвращает добавление дополнительных битов к восстановленным данным. Вот этот момент как раз реализован в рассматриваемой функции неправильно.


Если вы нашли ошибку, вы молодец. Если нет, то это тоже нормально. Нужно вникать в код, чтобы заметить, что что-то идёт не так. Анализатор про это "что-то не то" сообщает предупреждением: V547 [CWE-571] Expression 'extraBytes > 0' is always true. FBXUtil.cpp 224


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


// calculate extra bytes needed to get a multiple of 3size_t extraBytes = 3 - length % 3;

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


size_t extraBytes = length % 3;

Тогда, если обрабатывается, например, 5 байт, то получаем 5 % 3 = 2, и нужно дополнительно обработать 2 байта. Если на вход поступило 6 байт, то ничего отдельно обрабатывать не нужно, так как 6 % 3 = 0.


Но программист перемудрил и написал бессмысленный код:


size_t extraBytes = 3 - length % 3;

И как раз при анализе этого кода анализатору и понадобился механизм анализа потока данных. Какое бы значение не находилось в переменной length, после деления по модулю будет получено значение в диапазоне [0..2]. Анализатор PVS-Studio умеет работать с диапазонами, точными значениями и множествами. Т. е. речь идёт про Value Range Analysis. В данном случае будет использован именно диапазон значений.


Продолжим вычисления:


size_t extraBytes = 3 - [0..2];

Получается, что переменная extraBytes никогда не будет равна нулю. Анализатор вычислит следующий возможный диапазон её значений: [1..3].


До момента проверки, переменная нигде не изменяется. Следовательно, анализатор совершенно прав, предупреждая, что результатом проверки всегда будет истина:


if (extraBytes > 0)

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


Конечно, некорректность работы функции не ограничивается тем, что будет выполнять фрагмент кода, который выполняться не должен. Там вообще всё идёт вкривь и вкось. Предположим, что требуется закодировать 6 символов. В этом случае выходная строка должна содержать 8 символов. Давайте быстренько прикинем, как поведёт себя рассмотренная функция.


// calculate extra bytes needed to get a multiple of 3size_t extraBytes = 3 - length % 3; // 3-6%3 = 3// number of base64 bytessize_t encodedBytes = 4 * (length + extraBytes) / 3; // 4*(6+3)/3 = 12std::string encoded_string(encodedBytes, '=');

Уже получилось, что выходная строка будет содержать 12 символов, а не 8. Дальше тоже всё будет работать неправильно даже нет смысла вдаваться в подробности.


Вот так легко и просто статический анализ нашёл ошибку в коде. А представьте, ведь кто-то будет мучиться и отлаживаться, чтобы понять, почему неправильно происходит кодирование символов в кодировку Base64. Здесь мы, кстати, подходим к вопросу качества используемых сторонних библиотек, который я рассматривал в публикации "Почему важно проводить статический анализ открытых библиотек, которые вы добавляете в свой проект".


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


Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. Why PVS-Studio Uses Data Flow Analysis: Based on Gripping Error in Open Asset Import Library.

Подробнее..

Обзор последних изменений в rotorе (v0.10 v0.14)

20.02.2021 08:20:29 | Автор: admin

actor system


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


Общий интерфейс для таймеров (v0.10)


Таймеры сами по себе вездесущи во всех акторных фрейморках, т. к. они делают программы более надёжными. До v0.10 не было API для того, чтобы взвести таймер; это можно было сделать только посредством доступа к низлежащему движку событий (event loop) и использованию соответствующего API, разного для разных движков. Это было не очень удобно и ломало абстракции: кроме доступа к API движка, нужно было в обработчике таймера использовать низкоуровневый API rotor'а, чтобы работала доставка сообщений. Кроме того, отмена таймера также имеет свои особенности в каждом цикле событий, что захламляло ненужными деталями логику работы актора.


Начиная с v0.10 в rotor'е, можно делать что-то вроде:


namespace r = rotor;struct some_actor_t: r::actor_base_t {    void on_start() noexcept {        timer_request = start_timer(timeout, *this, &some_actor_t::on_timer);    }    void on_timer(r::request_id_t, bool cancelled) noexcept {        ...;    }    void some_method() noexcept {        ...        cancel_timer(timer_id);    }    r::request_id_t timer_id;};

Надо отметить, что к моменту завершения работы актора (shutdown_finish), все взведённые таймеры должны сработать или быть отменены, иначе это ведёт к неопределённому поведению (undefined behavior).


Поддержка отмены запросов (v0.10)


По-моему мнению, у всех сообщений в caf семантика "запрос-ответ", в то время как в sobjectizer'е все сообщения имеют обычную "отправил-и-забыл" ("fire-and-forget") семантику. rotor поддерживает оба типа, причём по-умолчанию сообщения являются "отправил-и-забыл", а "запрос-ответ" можно сделать поверх обычных сообщений.


В обоих фреймворках, caf и sobjectizer, у каждого актора есть управляемая очередь сообщений, что обозначает, что фреймворк не доставляет новое сообщение, пока предыдущее не было обработано. В противоположность этим фреймворкам, в rotor'е нет управляемой очереди сообщений, что обозначает, что актор сам должен создать свою собственную очередь и заботиться о перегрузках при необходимости. Для мгновенно обрабатываемых сообщений типа "пинг-понг" это не имеет особого значений, однако для "тяжёлых" запросов, которые в процессе своей обработки делают ввод-вывод (I/O), разница может быть существенна. Например, если актор опрашивает удалённую сторону через HTTP-запросы, нежелательно начинать новый запрос, пока предыдущий ещё не закончился. Ещё раз: сообщение не доставлено, пока предыдущее не обработано, и не важно, что за типа сообщения.


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


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


namespace r = rotor;namespace payload {struct pong_t {};struct ping_t {    using response_t = pong_t;};} // namespace payloadnamespace message {using ping_request_t = r::request_traits_t<payload::ping_t>::request::message_t;using ping_response_t = r::request_traits_t<payload::ping_t>::response::message_t;using ping_cancel_t = r::request_traits_t<payload::ping_t>::cancel::message_t;} // namespace messagestruct some_actor_t: r::actor_base_t {    using ping_ptr_t = r::intrusive_ptr_t<message::ping_request_t>;    void on_ping(ping_request_t& req) noexcept {        // just store request for further processing        ping_req.reset(&req);    }    void on_cancel(ping_cancel_t&) noexcept {        if (req) {            // make_error is v0.14 feature            make_response(*req, make_error(r::make_error_code(r::error_code_t::cancelled)));            req.reset();        }    }    // простейшая "очередь" из одного сообщения.    ping_ptr_t ping_req;};

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


std::thread backend/supervisor (v0.12)


Это давно ожидаемая возможность, которая делает rotor похожим на sobjectizer: в случае, когда актору нужно осуществить блокирующие операции и ему не нужен никакой цикл событий. Например, обработчик сообщений должен выполнить интенсивные вычисления на центральном процессоре.


Очевидно, что во время блокирующих операций нет возможности сработать таймерам или другим сообщениям быть доставленными. Другими словами, во время блокирующих операций актор теряет свою реактивность, так как он не может реагировать на входящие сообщения. Чтобы преодолеть это, блокирующие операции должны быть разбиты на более мелкие итеративные куски; а когда актор закончит обрабатывать текущий кусок работы, он посылает себе сообщение с номером следующего куска для обработки, и так далее, пока все части не будут обработаны. Это даст текущему потоку выполнения немного воздуха, чтобы доставить другие сообщения, выполнить код, связанный с истекшими таймерами и т.п. Например, вмето того, чтобы вычислять свёртку sha512 для всего файла размером 1TB, задание может быть разделено на вычисление свёрток помегабайтово, что сделает поток вычисления достаточно реактивным. Данный подход универсален и применим для любого актороного фреймворка.


Само собой разумеется, что целая иерархия акторов может быть запущена на std::thread бэкенде, не только один актор. Следующий нюанс, на который следует обратить внимание, это то, что rotor'у надо подсказать, какие обработчики сообщений "тяжёлые" (блокирующие), чтобы обновить таймеры после этих обработчиков. Это делается во время подписки, т.е.:


struct sha_actor_t : public r::actor_base_t {    ...    void configure(r::plugin::plugin_base_t &plugin) noexcept override {        r::actor_base_t::configure(plugin);        plugin.with_casted<r::plugin::starter_plugin_t>([&](auto &p) {            p.subscribe_actor(&sha_actor_t::on_process)->tag_io(); // важно        });    }

Полный исходный код реактивного актора, который вычисляет свёртку sha512, который реагирует на CTRL+c, доступен по ссылке.


Идентификация Акторов (v0.14)


Канонический способ идентификации актора по основной адресу (в rotor'е у актора может быть несколько адресов, аналогично как в sobjectizer'е агент может быть подписан на несколько mbox'ов). Однако, иногда желательно вывести в лог имя актора, который завершил работу, в соответствующем колбеке в его супервайзере:


struct my_supervisor_t : public r::supervisor_t {    void on_child_shutdown(actor_base_t *actor) noexcept override {        std::cout << "actor " << (void*) actor->get_address().get() << " died \n";    }}

Адрес актора динамичен и меняется при каждом запуске программы, так что эта информация почти бесполезна. Чтобы она имела смысл, актор должен напечатать свой основной адрес, где, например, в перекрытом методе on_start(). Однако, это решение не очень удобно, поэтому было решено ввести свойство std::string identity непосредственно в базовый класс actor_base_t. Таким образом, идентичность актора может быть выставлена в конструкторе или во время конфигурации плагина address_maker_plugin_t:


struct some_actor_t : public t::actor_baset_t {    void configure(r::plugin::plugin_base_t &plugin) noexcept override {        plugin.with_casted<r::plugin::address_maker_plugin_t>([&](auto &p) {            p.set_identity("my-actor-name", false);        });        ...    }};

Теперь можно выводить идентичность актора в его супервайзере:


struct my_supervisor_t : public r::supervisor_t {    void on_child_shutdown(actor_base_t *actor) noexcept override {        std::cout << actor->get_identity() << " died \n";    }}

Иногда акторы уникальны в одной программе, а иногда сосуществуют несколько экземпляров одного и того же класса акторов. Чтобы различать между их, адрес каждого может быть добавлен к имени актора. В этом и смысл второго параметра bool в методе set_identity(name, append_addr) выше.


По умолчанию идентичность актора равна чему-то вроде actor 0x7fd918016d70 или supervisor 0x7fd218016d70. Эта возможность появилась в rotor'е начиная с версии v0.14.


Extended Error вместо std::error_code, shutdown reason (v0.14)


Когда случается что-то непредвиденное в процессе обработки запроса, до версии v0.14, ответ содержал код ошибки в виде std::error_code. Такой подход хорошо служил своей цели, но, ввиду, иерархичной природы rotor'а, этого оказалось не достаточно. Представим себе случай: супервыйзер запускает двух акторов, и у одного из них произошёл сбой в инициализации. Супервайзер экскалирует проблему, т. е. выключается сам и шлёт запрос на выключение второму актору. Однако, на момент, когда второй актор выключился, исходный контекст уже был потерян, и совершенно неясно, почему он выключился. А причина кроется в том, что std::error_code не содержит в себе достаточно информации.


Поэтому было решено ввести собственный класс расширенной ошибки rotor::extended_error_t, который содержит std::error_code, std::string в качестве контекста (обычно это идентичность актора), а также умный указатель на следующую расширенную ошибку, что вызвала текущую. Теперь схлопывание иерархии акторов может быть представлено цепочкой расширенных ошибок, где причина выключения каждого актора может быть отслежена:


struct my_supervisor_t : public r::supervisor_t {    void on_child_shutdown(actor_base_t *actor) noexcept override {        std::cout << actor->get_identity() << " died, reason :: " << actor->get_shutdown_reason()->message();    }}

выведет что-то вроде:


actor-2 due to supervisor shutdown has been requested by supervisor <- actor-1 due initialization failed

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

Подробнее..

Почему lsFusion, а не 1С?

02.03.2021 10:09:04 | Автор: admin


Предыдущая статья Почему не 1С? вышла больше года назад и вызвала достаточно живой интерес (совсем немного не дотянула до 100к просмотров и 2к комментариев). Впрочем, как и ожидалось, у многих возник резонный вопрос: Если не он, то кто? Безусловно, как многие поняли, та статья писалась не просто так, а чтобы вслед за ней выпустить еще одну статью, где было бы рассказано, как описанные в первой статье проблемы можно и нужно решать. Однако, по различным причинам, выпуск этой ответной статьи был отложен на весьма долгое время. Но, как говорится, лучше поздно, чем никогда.


Как было отмечено в заключении предыдущей статьи, в качестве решения всех описанных в предыдущей статье проблем предлагается использовать платформу (и одноименный язык) lsFusion. Эта платформа имеет в основе несколько достаточно редких, но при этом наиболее высокодекларативных парадигм программирования: комбинаторное (function-level, не путать с functional), реактивное, событийно-ориентированное, программирование на ограничениях (constraint) и метапрограммирование. Впрочем, для неискушенного читателя это все не более чем набор красивых buzzwords, поэтому не будем уделять много внимания теории, а сразу перейдем на более практический уровень, а именно к решению описанных в предыдущей статье проблем.


Структура этой статьи полностью повторяет структуру статьи Почему не 1С? (с теми же названиями разделов и в том же порядке):


Оглавление


При этом в каждом разделе, с названием проблемы в 1С, рассказывается как данная проблема решается в lsFusion.


Объекты: Справочники, Документы и т.д.


В lsFusion основной акцент сделан не на объекты, а на функции и поля (в lsFusion они объединены в одно понятие свойства). Такой подход позволяет обеспечить прежде всего гораздо более высокую модульность и производительность (об этом в следующих разделах). Впрочем, безусловно, у инкапсуляции тоже есть свои преимущества например, механизмы копирования и версионирования объектов из коробки. Правда, при использовании всех такого рода механизмов, существует два нюанса:


  • Как правило, все эти механизмы достаточно эвристичны и либо включают лишние данные (например, какую-нибудь сугубо техническую информацию, если она хранится в самом объекте), либо, наоборот, какие-то данные не включают (например, если эти данные хранятся в отдельных таблицах / регистрах, но все равно логически относятся к объекту). Соответственно, эти автоматические механизмы все равно приходится донастраивать вручную, что уничтожает практически все преимущество их автоматичности.
  • Все эти механизмы всегда можно надстроить сверху (что в lsFusion уже делается и / или будет сделано в следующих версиях), получив тем самым преимущества обоих подходов.

Неэффективное получение данных объектов


Так как для выполнения логики вычислений lsFusion пытается максимально использовать SQL-сервер, а не сервер приложений (причем делает это максимально группируя запросы, чтобы выполнять их как можно меньше), операции чтения объекта целиком в lsFusion не существует в принципе. Как следствие, и проблема N+1 и проблема избыточного чтения в lsFusion возникают крайне редко. Например следующее действие:

fillSum(Invoicei){
FORinvoice(InvoiceDetailid)=iDO
sum(id)<-price(id)*quantity(id);
}
Скомпилируется в одно действие:
fillSum(Invoicei){
sum(InvoiceDetailid)<-price(id)*quantity(id)WHEREinvoice(id)=i
}
Которое, в свою очередь, выполнится одним запросом, в котором будут читаться / писаться только используемые ряды / колонки.

Таблицы / Представления: Регистры


В lsFusion все те абстракции, которые намешаны в регистрах 1С, достаточно четко разделены, что, с одной стороны, дает лучшее понимание того, что происходит под капотом (а значит, упрощает оптимизацию производительности), а с другой стороны дает куда большую гибкость. Так, абстракции из регистров отображаются на абстракции lsFusion следующим образом:


  • Таблицы первичные свойства
  • Представления свойства, реализуемые при помощи остальных операторов (впрочем, материализованные свойства можно также рассматривать и как таблицы)
  • Работа с моментами / периодами времени частный случай представлений, свойства, реализуемые при помощи операторов группировки:
    • СрезПоследних GROUP LAST
    • Остатки, Обороты SUM (ОстаткиИОбороты в lsFusion не имеют смысла, так как оптимизатор lsFusion умеет сам объединять подзапросы, если это необходимо)

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


Единственное, что еще хотелось бы отметить. Возможно в lsFusion все же имеет смысл добавить синтаксический сахар по созданию всего этого комбайна из класса регистра, агрегации, а также набора готовых свойств остатков и оборотов. Что-то вроде:

LEDGERSalesGROUPStockstock,SkuskuSUMNUMERICquantity,NUMERICsum;

//автоматическисоздаетклассSalesисвойства:
//stock,sku,quantity,sum=ABSTRACTStock,Sku,NUMERIC,NUMERIC(Sales);-
соответствующиеизмерения/ресурсы
//quantitySales,sumSales(stock,sku)-текущийостаток(имя=имясвойства+имярегистра)
//quantitySales,sumSales(stock,sku,DATETIME)-текущийостатокнадату
//quantitySales,sumSales(stock,sku,DATETIME,DATETIME)-оборотысдатыподату
//ит.п.
И в следующих версиях такой синтаксический сахар скорее всего появится. Другое дело, что чаще всего в сложных проектах регистры имеют более сложную структуру (например, наследуются друг от друга, денормализуют данные для составных индексов, расширяются в разных модулях и так далее), поэтому такой сахар может быть важен разве что для RAD разработки (а точнее прототипирования), которая в современном IT-мире уже не так актуальна.

Регистры поддерживаются в очень частных случаях


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


В отличие от 1С, в lsFusion поддерживается материализация не только суммы и последних по дате значений, но и практически любых вычисляемых данных. Так, в lsFusion можно материализовать:


  1. Композицию, что, например, позволяет прозрачно денормализовывать данные из разных таблиц (это будет показано в разделе "Статичная физическая модель").
  2. Максимумы / минимумы / последние значения по любому полю, что позволяет эффективно организовывать нумерацию и ранжирование данных.
  3. Рекурсию, что, например, позволяет разворачивать иерархию в плоские таблицы (с такой же высокой производительностью).
  4. Выбор (полиморфизм), что позволяет наследовать регистры друг от друга.
  5. И многие другие

Отсутствие ограничений и событий для значений регистров


lsFusion поддерживает ограничения и события в общем случае, причем, в том числе, для вычисляемых нематериализованных данных. Так, например, для создания ограничения, что остаток (который может вычисляться с использованием любого количества различных данных / операторов) должен быть больше 0, достаточно написать всего одну строку:

CONSTRAINTcurrentBalance(sku,stock)<0MESSAGE'Остатокнеможетбытьотрицательным';
Соответственно, платформа будет сама максимально эффективно (инкрементальными вычислениями) проверять, что никакое изменение (например, изменение склада прихода или количества расхода), это ограничение не нарушит.

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

WHENSET(currentBalance(Skusku,Stockstock)<0)//когдаостатокстановитсяменьше0
EMAILSUBJECT'Остатокнаскладе'+address(stock)+'длятовара'+name(sku)+
'сталменьше0'TOresponsibleEmail(group(sku));

В параметрах виртуальных таблиц можно использовать только константы


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

EXPORTFROMprice(Skusku),balance(date(sku),sku)WHEREname(sku)='Колбаса';
Платформа автоматически протолкнет условие ограничивающее наименование (и как следствие даты, на которые будет вычисляться остаток) внутрь подзапроса (и всех подзапросов внутри этого подзапроса), таким образом выполнив оптимизацию predicate push down . Причем в отличии от того же SQL, платформа умеет выполнять эту оптимизацию не только для группировок, но и для разбиений и даже для рекурсий. Впрочем это тема для отдельной статьи, подробно на ней здесь останавливаться не будем.

Запросы


Как уже говорилось выше, lsFusion все вычисления пытается выполнять максимально на SQL сервере (для обеспечения максимальной производительности), таким образом абсолютное большинство абстракций платформы можно скорее отнести к логике запросов, чем к логике процедур. Так, к логике запросов можно отнести всю логику свойств и форм, поэтому проводить аналогии будет правильно именно с этими двумя абстракциями.


Запросы в строках


И логика свойств и логика форм задаются непосредственно на языке lsFusion, соответственно для них:


  • в IDE поддерживается полный арсенал разработчика автоподстановка, подсветка ошибок, синтаксиса, поиск использований и т.п.
  • Большинство ошибок обнаруживаются либо на уровне IDE (чаще всего), либо при запуске сервера, что значительно повышает и скорость разработки и надежность разрабатываемых решений.

Тут конечно иногда возникают вопросы с динамическими формируемыми запросами, но как правило они решаются использованием либо соответствующих условных операторов / опций (IF, SHOWIF и т.п.), либо оператора выполнения программного кода (EVAL), позволяющего выполнить любую заданную строку кода на lsFusion.


Отсутствие оптимизатора запросов


В lsFusion внутри очень мощный механизм оптимизации запросов, во многих случаях выполняющий оптимизации, которые не умеют выполнять даже дорогие коммерческие СУБД (не говоря уже о PostgreSQL). Так, все проблемы с производительностью описанные в статье Почему не SQL, lsFusion умеет решать самостоятельно без каких-либо дополнительных действий со стороны разработчика, который, соответственно, может сконцентрироваться на решении бизнес-задач, а не думать как правильно написать запрос и / или в какую временную таблицу положить его результат.


Так пример из статьи про 1С в lsFusion будет выглядеть следующим образом:


Пример из статьи
ВБРАТЬ    РасходнаяНакладнаяСостав.Номенклатура,    УчетНоменклатурыОстатки.КоличествоОстатокИЗ    Документ.РасходнаяНакладная.Состав КАК РасходнаяНакладнаяСостав        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.УчетНоменклатуры.Остатки(,                             Номенклатура В (                                   ВБРАТЬ Номенклатура                                   ИЗ Документ.РасходнаяНакладная.Состав                                   ГДЕ Ссылка = &Документ)) КАК УчетНоменклатурыОстатки        ПО УчетНоменклатурыОстатки.Номенклатура = РасходнаяНакладнаяСостав.НоменклатураГДЕ    РасходнаяНакладнаяСостав.Ссылка = &Документ И    (УчетНоменклатурыОстатки.КоличествоОстаток < РасходнаяНакладнаяСостав.Количество ИЛИ        УчетНоменклатурыОстатки.КоличествоОстаток ЕСТЬ NULL)
currentBalance(InvoiceDetailid)=currentBalance(sku(id));

export(Invoicei){
EXPORTFROMsku(InvoiceDetailid),currentBalance(id)WHEREinvoice(id)=iAND
currentBalance(id)<quantity(id)ORNOTcurrentBalance(id);
}
Соответственно никаких Номенклатура В ( ВБРАТЬ Номенклатура ИЗ Документ.РасходнаяНакладная.Состав ГДЕ Ссылка = &Документ) в lsFusion писать не надо.

Отсутствие расширенных SQL возможностей


Кроме классического набора операций в SQL-92, состоящего из группировок и композиций (аналог в SQL соединения), в lsFusion также поддерживаются операции:


  • Разбиение / упорядочивание (аналог в SQL оконные функции)
  • Рекурсия (аналог в SQL рекурсивные CTE)
  • Полиморфизм (косвенный аналог в SQL наследование таблиц)

Причем те же рекурсии в lsFusion поддерживаются в общем случае без каких-либо дополнительных ограничений (вроде невозможности использования GROUP BY в запросе шага).


Отсутствие запросов на изменение


Большинство ERP-платформ хотя формально и поддерживают ORM механизмы, но на практике, из-за плохой производительности, решения на ERP-платформах все равно в абсолютном большинстве случаев используют запросы на SQL-подобных языках.


Впрочем, в том же 1С запросы поддерживаются только для операций чтения данных, для записи все-таки приходится использовать ORM механизмы, производительность которых оставляет желать лучшего. В lsFusion такой проблемы нет, и все операции, в том числе создание объектов, могут выполняться на сервере БД, причем одним запросом. Например:

generateCards(){
FORiterate(i,1,10000)NEWd=DiscountCardDO
number(d)Card:+i;
}

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

Тоже самое касается и механизма изменения / удаления большого количества данных / объектов:

FORsum(DiscountCardd)>10000DO
vip(d)TRUE;
FORsum(DiscountCardd)>10000DO
DELETEd;
Скомпилируется в:
sum(DiscountCardd)TRUEWHEREsum(d)>10000;
DELETEDiscountCarddWHEREsum(d)>10000;
И опять-таки выполнится одним запросом.

Отказ от автоматических блокировок


Проблема блокировок (и вообще целостности данных) была достаточно подробно описана в статье про 1С, поэтому повторяться здесь особого смысла я не вижу. Там же был описан и один из самых простых и эффективных методов ее решения:


  1. Использовать версионные СУБД (или версионный режим в том же MS SQL).
  2. Повысить уровень изоляции базы до Repeatable Read или еще лучше до Serializable.
  3. Материализовать данные, для которых важна целостность.
  4. Все транзакции с конфликтами записей или дедлоками откатывать и повторять заново.

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


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

Формы


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


Отказ от единого потока выполнения: разделение логики на сервер и клиент


В отличие от 1С в lsFusion поток выполнения един и для сервера, и для клиента. Такое единство значительно упрощает взаимодействие с пользователем / клиентским устройством с точки зрения процесса разработки. Так, пример в статье про 1С написан именно на языке lsFusion, и, соответственно, выглядит следующим образом:

f()<-someData();//читаемданныеизбазынеобходимыедляmyForm
DIALOGmyFormOBJECTSaINPUTDO//ОткрытьФормуМодально,пользователь
выбираеткакой-тообъект
IFisSomething(a)DO//читаемданныедляэтогообъектаиеслиснимичто-то
нето
DIALOGotherFormOBJECTSb=aDO{//ОткрытьФормуМодально,открываем
другуюформугдепользовательвыбираетдругойобъектb
g(b)<-someInput(b);//записываемданныедляb
APPLY;//сохраняемизменениявбазу
}
В какой-то степени lsFusion использует подход обычных форм в 1С, только делает это гораздо более масштабируемо и производительно. Фактически, вся магия асинхронности остается под капотом, а разработчик может сконцентрироваться строго на решении бизнес-задач, а не думать о том, где и как должен выполнять написанный им код.

Тут может возникнуть впечатление, что в lsFusion вообще не существует возможности выполнять заданный код на клиенте (в смысле кроме уже встроенных в платформу операторов/действий). Но это не так, в lsFusion существует специальная опция CLIENT в операторе INTERNAL, которая позволяет выполнить заданный именно на клиенте код. Для десктоп клиента этот код задается на Java, а для веб-клиента на JavaScript. Правда обычно такая тонкая настройка нужна очень редко, поэтому подробно останавливаться на ней здесь особого смысла нет.


Отказ от синхронности


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


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


Отказ от WYSIWYG: разделение интерфейса на запись и чтение


Как было подробно описано в предыдущей статье, у подхода 1С в построении интерфейсов, которые одновременно содержат и первичные и вычисляемые данные (для этого напомню используются динамические списки), есть как минимум 2 проблемы:


  • Из-за отсутствия оптимизатора, в динамических списках крайне противопоказано использовать подзапросы / виртуальные таблицы (представления).
  • Динамические списки нельзя редактировать.

Как следствие в 1С все интерфейсы по сути строго разделены на интерфейсы чтения и интерфейсы ввода. В lsFusion описанных двух проблем нет, и, как следствие, можно абсолютно декларативно строить максимально эргономичные и привычные пользователю Excel-style интерфейсы, вытаскивая на форму одновременно и данные, которые необходимо ввести, и данные, необходимые для принятия решения того, что именно надо вводить. Причем все построенные интерфейсы (как впрочем и остальные абстракции в lsFusion) реактивны из коробки автоматически обновляются при вводе / изменении данных пользователем. Впрочем на эту тему была отдельная статья, поэтому подробно останавливаться на этой теме здесь также не имеет особого смысла.


Невозможность обращаться в списках к реквизитам форм / текущим значениям других списков


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

FORMbalance
OBJECTSst=Stock,sk=Sku
PROPERTIES(st)name
PROPERTIESname(sk),currentBalance(st,sk)
FILTERScurrentBalance(st,sk)
;
При перемещении текущей записи в верхнем списке (складов), нижний список (товары, которые есть на выбранном складе) будет обновляться автоматически.

Избыточные уровни абстракции


Основным принципом при создании lsFusion был и остается принцип чистота и завершенность всех создаваемых абстракций. Так:


  • За один и тот же функционал в lsFusion отвечает ровно одна абстракция. Если для реализации некоторого функционала можно использовать уже существующие абстракции их нужно использовать. Такой подход значительно упрощает как изучение платформы разработчиками, так и разработку самой платформой.
  • Все абстракции выстроены в уровни (верхние используют нижние) таким образом, что если какая то абстракция разработчика не устраивает, он всегда может спуститься на уровень ниже, тем самым получить большую гибкость (правда при этом выполнив больше работы).
    Графически такая иерархия выглядит следующим образом:


Как следствие, количество абстракций в lsFusion значительно меньше чем в 1С. Соответственно взглянем на абстракции 1С из предыдущей статьи глазами lsFusion:


  • Объекты / записи

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


  • Объекты / ссылки на объекты

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


  • Данные формы / Данные объектов

В lsFusion поддерживается практически абсолютная реактивность на всех уровнях, в том числе на уровне форм. Соответственно необходимости в каких-то дополнительных абстракциях вроде данных формы в lsFusion попросту нет. Есть просто данные, и соответственно при любом их изменение платформа автоматически обновляет все представления их использующие. Если же форме нужны какие-то свои локальные данные, разработчик просто создает необходимые локальные первичные свойства, и работает с ними также как и со всеми остальными свойствами (например хранящимися в базе). То есть никаких крышесносящих РеквизитФормыВЗначение в lsFusion нет.


  • Запросы / СКД / Аналитика (BI)

Тут все немного сложнее. Запросов, как уже упоминалось в разделе объекты / записи в lsFusion нет (за их формирование и выполнение отвечает сама платформа). Остальной функционал выбора, объединения и отображения данных (не только из этого пункта, а вообще) в lsFusion соответствует следующим механизмам:


  • Печатные формы печатное представление формы, дизайн которого задается при помощи JasperReports, одной из самых распространенных систем отчетности под Java. Позволяет строить pixel-perfect формы, и вообще обладает огромным количеством различных возможностей.
  • Встроенная аналитика одно из представлений списка объектов формы, поддерживает графики, диаграммы, сводные таблицы и многое другое.
  • Сложные интерактивные формы с вычисляемыми данными обычное интерактивное представление формы позволяет отображать как первичные, так и вычисляемые данные, а также создавать сразу много списков объектов и связывать их друг с другом одной строкой кода (в разделе выше был пример).
  • Программный интерфейс работы с данными структурированное представление формы, позволяет экспортировать (и наоборот импортировать) любую форму в JSON, XML, XLSX, DBF и другие распространенные форматы.

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


Закрытая физическая модель


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


Открытая и прозрачная физическая модель дает массу преимуществ:


  1. Простая и очень производительная интеграция со сторонними инструментами (например BI).
  2. Возможность использования стандартных средств администрирования БД (например, профайлеров)
  3. Читабельные запросы в журналах и логах.

Статичная физическая модель


PS: Так как большая часть статьи писалась на сутках (есть сейчас такое национальное развлечение в Беларуси) и самой статьи Почему не 1С? перед глазами у автора не было, многое писалось по памяти, и, как оказалось, этого и следующего недостатка в предыдущей статье не было вообще. Но, так как эти разделы уже были написаны, мы решили их все же включить в эту статью.


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

date=DATADATE(DocumentDetail)
barcode=DATASTRING(Sku);
sku=DATASku(DocumentDetail);

barcode(DocumentDetaildd)=barcode(sku(dd));
count(STRINGbc,DATEd)=GROUPSUM1IFdate(DocumentDetaildd)>dANDbarcode(dd)=bc;
FORMx
OBJECTSbc=STRINGPANEL,d=DATEPANEL
PROPERTIEScount(bc,d),VALUE(bc),VALUE(d)
;
При выполнении этой формы сформируется запрос в котором будет:
  1. JOIN с таблицей товаров, штрихкод в таблице SKU совпадает с заданным;
  2. подсчет количества строк документов по всем датам больше заданной.

При этом у SQL сервера будет два варианта: либо бежать по индексу по датам в таблице строк, либо бежать по индексу по штрихкодам в таблице товаров, находить товары, после чего бежать по индексу по Sku в таблице строк. В обоих случаях производительность будет оставлять желать лучшего (если движений одного товара очень много и товаров очень много). В lsFusion для решения этой проблемы достаточно изменить / добавить следующие строки:

barcode(DocumentDetaildd)=barcode(sku(d))MATERIALIZED;//помечает,что
должнобытьхранимое
INDEXbarcode(DocumentDetaildd),date(dd);//строимсоставнойиндекс
После такой оптимизации SQL сервер сможет начать использовать построенный составной индекс и производительность будет максимальной.

Закрытые исходники и лицензии


Открытые исходники и лицензия в последнее время стали де-факто стандартом в отрасли средств разработки. Даже Microsoft, известная ранее консервативностью в этом вопросе, открыла исходники .Net, сделала его бесплатным и выпустила версию под Linux.


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


lsFusion выпускается под LGPL v3 лицензией, которая подразумевает свободное использование, распространение и модификацию (за исключением выпуска коммерческой версии платформы), в общем практически все что угодно. Исходники доступны на GitHub. Это обычный Maven-проект, соответственно поддерживаются все стандартные циклы сборки Maven: compile, install, package и т.п. Также открыты исходники сервера сборки, плагина, управление проектами ведётся в GitHub Projects. То есть вся инфраструктура открыта настолько, насколько это возможно.


Отсутствие наследования и полиморфизма


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


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


Про то в каком именно виде в lsFusion поддерживаются наследование и полиморфизм уже неоднократно рассказывалось на хабре, как в формате tutorial, так и на конкретных примерах, поэтому повторяться тут не будем.


Отсутствие явной типизации в коде


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


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

invoice(InvoiceDetailid)=DATAInvoice;
sum=GROUPSUMsum(InvoiceDetailid)BYinvoice(id)//уsumсчитаетсяестьодин
параметрклассаInvoice(путемвыводаклассазначенияinvoce,вданномслучае-Invoice)

FORMmyForm
OBJECTSmyObject=MyClass
;
filtered=FILTERmyForm.myObject;//уfilteredсчитаетсяестьодинпараметркласса
MyClass(выводитсяизклассаобъектаmyObjectформыmyForm)

Отсутствие модульности


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


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


  1. События предметной области (и все то, что на них построено ограничения и агрегации) позволяют разбить всю бизнес-логику на множество небольших напрямую независимых друг от друга правил. Эти правила, в свою очередь, автоматически выстраиваются платформой в один большой поток выполнения, в зависимости от того, какие данные эти правила изменяют / используют.
  2. Расширения позволяют расширять практически все существующие в платформе абстракции. Такая возможность опять-таки позволяет максимально декомпозировать любую сложную бизнес-логику (например, сложные формы).
  3. Множественные наследование и полиморфизм дают все преимущества ООП, основным из которых является все та же декомпозиция (а значит и модульность). Отметим, что полиморфизм в какой-то степени являются частным случаям расширений (то есть они расширяют существующее абстрактное свойство / действие, добавлением к нему новых реализаций).
  4. Отказ от инкапсуляции и акцент на данных, а не объектах (это уже упоминалось в самом первом разделе). Впрочем, тут конечно важно не отсутствие синтаксического сахара в виде this, а то, что классы в lsFusion получаются по сути открытыми, то есть опять-таки расширяемыми.
  5. Метапрограммирование позволяет осуществлять шаблонизацию кода, тем самым значительно уменьшая его дублирование, а значит опять-таки (пусть и косвенно) повышая модульность создаваемых решений

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


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


Ставка на визуальное программирование


В предыдущей статье были подробно расписаны все недостатки ВП, и скорее всего, именно поэтому подход Everything as code стал золотым стандартом в мире современной разработки. Именно такой подход используется и в lsFusion.


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


Фатальный недостаток


Вообще, проблема переписывания всего, что только можно, это проблема не только 1С, но и многих других ERP-платформ. Обусловлено это, видимо, историческим наследием, и имеет как минимум две проблемы:


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

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


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


    Но естественно, поддержка языка lsFusion делалась не с нуля для создания серверных парсера и лексера в lsFusion используется ANTLR, для того же самого в IDEA используется Grammar-Kit (парсер), JFlex (лексер).

  2. UI. Для реализации десктоп-клиента используется Java SE (Swing, Web Start), что позволило получить поддержку сразу всех ОС, а также обновление и установку клиентского приложения прямо из коробки. Впрочем, как уже говорилось в одной из предыдущих статей, основным клиентом в текущей и следующих версиях будет веб-клиент, поэтому подробно на особенностях реализации десктоп-клиента останавливаться не будем.


    Для реализации веб-клиента в lsFusion используется:

    • GWT позволяет использовать Java и на сервере(ах), и на клиенте. Плюс, что, наверное, все же более важно, GWT позволяет разрабатывать клиента на типизированном языке с полиморфизмом и наследованием, без чего разработка столь функционального и одновременно быстрого клиента была бы гораздо сложнее. Кроме того GWT имеет достаточно бесшовную интеграцию с JavaScript, и соответственно позволил нам использовать огромное количество существующих JavaScript библиотек


      Тут многие могут заметить, что GWT уже полумертв, и сейчас использование того же TypeScript было бы логично. Но:


      а) при начале разработки веб-клиента TypeScript ещё только-только появился;


      б) разработчик на lsFusion напрямую с GWT не сталкивается, поэтому его наличие в структуре ни на что не влияет, и при необходимости клиентскую часть всегда можно перевести на любую другую технологию.


      Но когда-нибудь миграция на TypeScript, я думаю, все же случится.

    • Full Calendar, Leaflet используются для поддержки нестандартных представлений списков (календаря и карты).
    • Spring Security, MVC, DI используются для задач аутентификации, управления сессиями, а также инициализации серверов (веб, приложений).
  3. BI для задач внутренней аналитики в lsFusion используется представление сводная таблица. Для реализации этого представления используются:

    • pivot-table, subtotal для пользовательской настройки BI, отрисовки таблиц (в том числе с подитогами),
    • plotly для отрисовки графиков и диаграмм,
    • tableToExcel для выгрузки сводных таблиц в Excel (с сохранением форматирования, collapsible рядов и т.п.).

    Тут стоит отметить, что первая и третья библиотеки достаточно серьезно доработаны (во всяком случае, первая), но в этом и заключается сила open-source, если что-то в технологии не устраивает разработчик всегда может сам изменить технологию под свои нужды.

  4. Печатные формы. Для работы с печатными формами в lsFusion используется одна из самых популярных технологий в этой области JasperReports.


    Тут стоит отметить вот какую особенность. В 1С по непонятным причинам технология работы с печатными формами объединена с инструментами аналитики, что, на мой взгляд, достаточно странно, так как:


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


    б) аналитические инструменты требуют определенную ячеистость, что с другой стороны усложняет построение pixel-perfect печатных форм.


    В lsFusion используется другой подход: инструменты аналитики объединены с обычными таблицами (используют те же rendererы, стили, события и т. п.), а печатные формы являются отдельным механизмом. Соответственно BI обладает интерактивностью обычных таблиц (переход по ссылке, детализация и т. п.), а печатные формы используются в основном для печати документов и периодичной отчетности (с минимальной кастомизацией).

  5. IDE. Когда мы начинали разработку плагина для IDE, IDEA ещё не была настолько популярна (Eclipse был существенно популярнее), поэтому выбирая IDEA мы изрядно рисковали. Ирония, но несмотря на меньшее сообщество, найти материал по разработке своего языка под IDEA оказалось проще, да и ее архитектура выглядела существенно более продуманно. Сейчас IDEA (а точнее IntelliJ Platform) практически без сомнения лидер на рынке IDE, обладает огромным количеством возможностей, практически все из которых поддерживаются при работе с lsFusion (либо из коробки, либо благодаря реализации необходимых доработок в lsFusion плагине). Плюс stub indexы, chameleon element'ы и многое другое позволяет обеспечить высокую производительность практически на любых объемах lsFusion кода (скажем, у меня в агрегированном проекте десятки проектов достаточно высокой сложности с сотнями тысяч строк кода, и все работает очень быстро).
  6. Система контроля версий. Everything as code позволяет использовать любую из существующих систем контроля версий, самой популярной из которых, безусловно, является Git. Впрочем, на некоторых проектах с непрерывной поставкой без крупных функциональных веток можно спокойно использовать тот же Subversion (что, например, мы и делаем на некоторых проектах).
  7. Система управления зависимости / сборки. Опять таки EaC позволяет использовать существующие системы управления зависимости / сборки в Java, наиболее распространенной из которых является Maven (так центральный репозиторий для lsFusion поддерживается на repo.lsfusion.org).


    Чтобы подключить сервер в Maven-проект достаточно в pom.xml добавить следующие строки:


    <repositories>        <repository>            <id>lsfusion</id>            <name>lsFusion Public Repository</name>            <url>http://repo.lsfusion.org</url>        </repository></repositories>
    

    Что еще важнее, через Maven очень легко подключать сторонние серверные Java библиотеки. Например, если нам надо решить СЛАУ, просто находим соответствующую библиотеку в центральном Maven репозитории, добавляем в pom.xml.


    <dependency>        <groupId>org.apache.commons</groupId>        <artifactId>commons-math3</artifactId>        <version>3.2</version></dependency>
    

    И эту зависимость автоматически подключат и IDE, и сервера сборки.

  8. Сервера приложений и БД. Для работы с серверами БД используется JDBC, при этом все проблемы с производительностью / соответствием спецификации решаются именно родными средствами СУБД. То есть никаких пропатченных версий Postgres не требуется (которых может не быть в центральных репозиториях Docker, yum и т.п.)


    Также сервер приложений использует несколько компонент Java Spring, что значительно упростило реализацию процессов инициализации и настройки сервера приложений и сделало эти процессы более стандартизированными.



Неуважительные по отношению к разработчикам лицензирование и брендирование


Как уже упоминалось выше, lsFusion распространяется под лицензией LGPL v3.0, которая позволяет все что угодно, кроме, разве что, создания коммерческой версии lsFusion и ее дальнейшей продажи. Соответственно, для разработчика платформа lsFusion не более чем инструмент для решения его задач, а не манна небесная, на которую он должен молиться и с которой его должны ассоциировать. Как следствие, основной ценностью в экосистеме lsFusion является не платформа как таковая, а решения на этой платформе, и что, возможно даже более важно, компетенции людей / компаний их дорабатывающих, внедряющих и поддерживающих. Почему именно такие акценты актуальны в современном ИТ-мире? Дело в том, что большинство бизнесов сейчас уже как-то автоматизировано, и, соответственно, основной вопрос заключается как раз в качестве этой автоматизации ее глубине, гибкости и соответствии существующим бизнес-процессам. А обеспечение всех этих требований требует как хорошо спроектированных модульных специализированных решений, так и умение быстро и качественно дорабатывать эти решения прямо на лету (так как, как правило, в крупных проектах внедрение сначала идет as is, а только потом to be). Соответственно грести все компании, использующие платформу, под одну гребенку, превращая их во франчей, в конечном итоге, не выгодно никому:


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

Другое дело, что некий общий каталог решений на lsFusion все равно может быть полезен (опять-таки и людям / компаниям использующим lsFusion, и их заказчикам), и такой каталог безусловно появится (хотя, наверное, все же в среднесрочной перспективе).


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


Ну и еще один важный момент. Как отмечалось выше, качество платформы критично прежде всего либо в крупных проектах (где бизнес-процессы как правило более сложные и уникальные), либо в узкоспециализированных решениях (где сам бизнес достаточно уникальный / редкий). В типовых решениях для малого и среднего бизнеса (особенно не сильно притязательных в плане IT) ценность платформы, как впрочем и самого решения, зачастую не очень высоки, поэтому сама логика рынка подсказывала сделать такие решения такими же бесплатными и открытыми (как сама платформа). Что мы собственно и сделали с решением MyCompany. Более того это решение выпускается даже под более свободной лицензией, чем сама платформа, что дает возможность сторонним разработчикам создавать на его основе свои специализированные решения, и, что еще более важно, дает возможность их продавать, тем самым зарабатывая на лицензиях.


Заключение


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


  1. В современном мире бизнес-приложений реальный экономический эффект могут дать только очень гибкие решения (быстро меняющиеся вместе с компанией), плюс, обладающие очень высокой глубиной автоматизации / кастомизации. И тут уже платформа выходит на первый план.
  2. Глобальная цифровизация всех каналов общения привела к тому, что многие, даже очень сложные, проекты разрабатываются и внедряются практически полностью онлайн (с буквально единичными очными встречами с заказчиком, более того, часто у самого заказчика все коммуникации внутри осуществляются исключительно онлайн). Как следствие, необходимость иметь физическое присутствие во всех регионах, где представлен заказчик, если не отпала, то стала гораздо менее острой. Соответственно, уже нет такой большой разницы между существованием 30 или 3000 поставщиков решения, на первый план опять-таки выходят уже другие факторы.

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


Так, среди таких пунктов можно вспомнить:

Существенный оверхед при работе с большими объектами (например документами)


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


Ограниченность пользовательских настроек


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


Невозможность одновременной работы с объектами (по аналогии например с Google docs)


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


Неудобная работа с динамическим количеством колонок


А именно в том случае, когда отображение колонок зависит от данных формы (и соответственно количество колонок может изменяться). Еще более непонятно, как это все увязывать с динамическими списками.


Отсутствие мгновенного контроля ссылочной целостности при удалении


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


  1. Пользователь может просто забыть, почему удалял тот или иной объект.
  2. Администратор, который по идее должен выполнять процесс удаления, может быть вообще не в курсе, что делать с возникающими битыми ссылками (по сути ему придется искать пользователей, которые удаляли эти объекты и спрашивать у них).

Неочевидные / неэргономичные интерфейсы для выполнения многих базовых действий


Например:


  • Настройка группировок настройка через списки, вместо интуитивных drag-drop интерфейсов.
  • Групповое изменение данных вообще не WYSIWYG операция, а находится где-то в администрировании (часть БСП как я понял).
  • Фильтрация если скажем необходимо отфильтровать все записи с текущим полем > заданного значения (закопана в Еще -> Настроить список, где необходимо найти нужную колонку и сделать еще несколько нажатий).
  • Подсчет количества записей, суммы по колонке честно говоря так и не нашел где это делается (но может просто плохо искал)

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


Невозможность прозрачной подмены представлений списков / свойств


Прозрачно заменить представление в 1С не может:


  • ни пользователь например, просто нажав соответствующую кнопку (как, например, в Odoo или lsFusion)
  • ни даже разработчик декларативно выбрав для отображения данных другой renderer, отличный от таблицы / поля, например, карту, спидометр или вообще любую js-функцию (причем так, чтобы обновлением данных продолжала заниматься сама платформа).

Ограниченность ряда абстракций (которые являются частными случаями)


Например, если необходимо:


  • организовать табличные части в табличных частях
  • реализовать классификатор на дату
  • реализовать несколько классификаторов (с выбором их пользователем)
  • организовать цепочку статусов документов (а не просто проведен / не проведен)
  • и т.п.

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



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


Подробнее..

День открытых данных 2021. Онлайн

01.03.2021 20:22:05 | Автор: admin

image


1-6 марта приглашаем на мероприятия, приуроченные к Международному Дню открытых данных 2021.


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


Рассказываем, какие мероприятия мы приготовили для участников в этом году.
Накануне Дня открытых данных, с 1 по 5 марта, проведем серию практических онлайн мастер-классов по работе с открытыми данными.


  • 1 марта, мастер-класс Вскрываем декларации. Как при помощи регулярных выражений привести Wordовскую табличку к пригодной для анализа форме. Доступна видеозапись.
  • 2 марта, мастер-класс О чем говорят депутаты Госдумы? Анализ текстовых данных на Python.
  • 3 марта, мастер-классы по работе с геопространственными данными и картами для новичков и профи.
  • 4 марта, мастер-класс по поиску открытых данных от DataMasters.
  • 5 марта, мастер-класс Российская официальная статистика: как сделать работу с данными удобнее, а данные понятнее?.
  • 5 марта, мастер-класс Визуализация данных в ObservableHQ.

6 марта пройдет онлайн-конференция День открытых данных.


В центре внимания вопросы о том, что происходит с открытостью в России и мире и как использовать данные для эффективного решения конкретных проблем и задач общества. В дискуссиях примут участие не только российские эксперты, но и представители крупнейших международных проектов, продвигающих ценности и идеологию открытых данных: Global Data Barometer, The Humanitarian Data Exchange.


В программе дискуссии и выступления:


  • Дискуссия. Бизнес на открытости: зачем заниматься открытым кодом и открытыми данными
  • Дискуссия. Как инструменты оценки влияют на открытость государства?
  • Дискуссия. Доступность данных о госфинансах
  • Дискуссия. Данные переписи населения 2021: приватность vs. польза для общества
  • Выступления. Что происходит с тематикой открытости в мире?

Программа и регистрация: opendataday.ru/msk. Трансляция будет доступна и бесплатна для всех желающих.


Подробнее..

FOSS News 57 дайджест материалов о свободном и открытом ПО за 15-21 февраля 2021 года

21.02.2021 22:15:46 | Автор: admin


Всем привет!


Продолжаем дайджесты новостей и других материалов о свободном и открытом ПО и немного о железе. Всё самое главное про пингвинов и не только, в России и мире. Бесконечность не предел: Linux и Open Source осваивают Марс; как прошёл FOSDEM 2021; Barclays и TD Bank присоединились к инициативе по защите Linux от патентных претензий; коммерциализация Open Source: плохой, хороший, злой; мнение эксперта: что делает Linux сильным, делает его и уязвимым; DARPA и Linux Foundation создают открытую инициативу для ускорения R&D разработок для 5G; пионер Python оценивает язык программирования после 30 лет существования и многое другое.


Оглавление


  1. Главное
    1. Бесконечность не предел: Linux и Open Source осваивают Марс
    2. Как прошёл FOSDEM 2021 на Matrix
    3. Barclays и TD Bank присоединились к инициативе по защите Linux от патентных претензий
    4. Коммерциализация Open Source: плохой, хороший, злой
    5. Мнение эксперта: что делает Linux сильным, делает его и уязвимым
    6. DARPA и Linux Foundation создают открытую инициативу для ускорения R&D разработок для 5G
    7. Пионер Python оценивает язык программирования после 30 лет существования
  2. Короткой строкой
    1. Новости
      1. Внедрения
      2. Внутренние дела организаций
      3. Ядро и дистрибутивы
      4. Специальное
      5. Мультимедиа
      6. Мобильные
      7. Безопасность
      8. AI & Data Science
      9. Web
      10. Для разработчиков
      11. Железо
    2. Статьи
      1. Внутренние дела организаций
      2. Ядро и дистрибутивы
      3. Специальное
      4. Базы данных
      5. Мультимедиа
      6. DevOps
      7. AI & Data Science
      8. Web
      9. Для разработчиков
      10. История
      11. Пользовательское
      12. Разное
    3. Релизы
      1. Ядро и дистрибутивы
      2. Специальное
      3. Мультимедиа
      4. Мобильные
      5. Безопасность
      6. DevOps
      7. AI & Data Science
      8. Web
      9. Для разработчиков
      10. Пользовательское
  3. Что ещё посмотреть
  4. Заключение

Главное


Бесконечность не предел: Linux и Open Source осваивают Марс


Категория: Новости/Ядро и дистрибутивы



ZDNet пишет: Ровер Perseverance вошёл в атмосферу Марса со скоростью почти 19 312 км/ч, и всего семь минут спустя NASA мягко и безопасно приземлила свой новый марсоход. На борту мобильной научной лаборатории весом в тонну находится её крошечный спутник беспилотный вертолет Ingenuity. Если все пойдёт хорошо, четырехфунтовый (1,8 кг) Ingenuity станет первым роботом, который когда-либо летал в другом мире. На расстоянии 11 световых минут от Земли невозможно управлять Ingenuity, он будет летать сам, используя Linux и созданную NASA программу, основанной на платформе F (произносится F prime производная от F) с открытым исходным кодом Лаборатории реактивного движения (JPL).


Подробности [ 1(en), 2(en)]


Как прошёл FOSDEM 2021 на Matrix


Категория: Статьи/Мероприятия



Linux.org.ru пишет: 67 февраля 2021 года прошла одна из крупнейших бесплатных конференций, посвящённая свободному программному обеспечению FOSDEM. Обычно конференция проводилась вживую в Брюсселе, но из-за пандемии коронавируса её пришлось перенести в онлайн. Для реализации этой задачи организаторы скооперировались с командой Element и выбрали чат на основе свободного протокола Matrix для построения федеративной сети коммуникаций в реальном времени, свободную VoIP-платформу Jitsi Meet для интеграции видеоконференций, и собственные инструменты для их автоматизации. Конференцию посетило более 30 тысяч пользователей, из которых 8 тысяч активные, а 24 тысячи гости.


Подробности []


Barclays и TD Bank присоединились к инициативе по защите Linux от патентных претензий


Категория: Новости/Внутренние дела организаций



OpenNET пишет: TD Bank, второй по размеру финансовый холдинг Канады, и Barclays, один из крупнейших мире финансовых конгломератов, вошли в число участников организации Open Invention Network (OIN), занимающейся защитой экосистемы Linux от патентных претензий. Участники OIN обязуются не выдвигать патентные претензии и безвозмездно разрешают использовать запатентованные технологии в проектах, связанных с экосистемой Linux. TD Bank заинтересован в поддержке экосистемы Linux, так как активно использует открытое ПО в своей инфраструктуре, финансовых сервисах и финтех-платформах. Barclays заинтересован в участии OIN для противостояния патентным троллям, не обладающих активами и досаждающих исками о нарушении сомнительных патентов к компаниям, внедряющим новые финансовые технологии.


Подробности [ 1, 2(en)]


Коммерциализация Open Source: плохой, хороший, злой


Категория: Статьи/Внутренние дела организаций



Tfir пишет:



В свежем выпуске Dirk & Swap: Разговоры об Open Source обсуждается тема, важная для роста и устойчивости проекта коммерциализация Open Source. Вот некоторые из тем, затронутых в этом обсуждении:


  1. Хотя коммерциализация проекта с открытым исходным кодом действительно способствует его устойчивости, имеет ли значение, кто его коммерциализирует. Git и Linux отличные примеры третьих сторон, таких как Github, Red Hat, SUSE, Canonical и т. д., которые коммерциализируют проекты, созданные Линусом Торвальдсом, в то время как он по-прежнему сосредоточен на разработке проекта. Правильно ли это, если третья сторона пытается коммерциализировать чужой проект?
  2. Следует ли нам скептически относиться к крупным корпорациям, таким как Microsoft, или беспокоиться, когда они начинают коммерциализировать проекты с открытым исходным кодом? Развенчаем некоторые мифы.
  3. Тем не менее, все ещё есть случаи, когда компании просто высасывают деньги из проектов с открытым исходным кодом, ничего не возвращая.
  4. Мы также говорили об Open Source и коммерческом Open Source или о том, что многие называют Open Core Software. Действительно ли это открытый исходный код, если он НЕ полностью открытый?


Подробности [(en)]


Мнение эксперта: что делает Linux сильным, делает его и уязвимым


Категория: Статьи/Безопасность



Ещё один материал от Tfir: Системы на базе Linux считаются более безопасными, чем другие платформы, но они не защищены от ошибок и атак. Эти системы так же уязвимы для ошибок и других векторов атак, как и, например, Windows. Всего несколько недель назад мы обнаружили уязвимость, связанную с sudo, которая присутствовала в системах Linux более десяти лет. Недавно мы узнали о ботнетах DreamBus и FreakOut, которые атакуют системы Linux. Короче говоря, хотя системы на базе Linux более мощны и предлагают большую гибкость для пользователей, они так же уязвимы, как и любая другая система. Чтобы глубже погрузиться в безопасность Linux, мы поговорили с Рональдом Никсоном, вице-президентом Polyverse, чтобы не только поговорить об этих уязвимостях, но и о том, как Polyverse на самом деле делает системы Linux действительно безопасными.


Подробности [(en)]


DARPA и Linux Foundation создают открытую инициативу для ускорения R&D разработок для 5G


Категория: Новости/Внутренние дела организаций



Linux Foundation пишет: Linux Foundation (LF), некоммерческая организация, обеспечивающая массовые инновации с помощью открытого исходного кода, объявила о подписании соглашения о сотрудничестве с Агентством перспективных исследовательских проектов Министерства обороны США (DARPA) для создания программного обеспечения с открытым исходным кодом, которое ускоряет исследования и разработки в области технологий правительством США. В соответствии с соглашением, DARPA и LF создадут широкую зону сотрудничества US GOV OPS, которая позволит проектам правительства США, их экосистеме и открытому сообществу участвовать в ускорении инноваций и безопасности в областях 5G, Edge, AI, стандартов, программируемости, IOT и других технологий. Формирование проекта смотивирует участников экосистемы поддерживать инициативы правительства США по созданию новейшего технологического программного обеспечения.


Подробности [ 1(en), 2(en)]


Пионер Python оценивает язык программирования после 30 лет существования


Категория: Статьи/Внутренние дела организаций



VentureBeat пишет: Языку программирования Python, который никогда не был так популярен как сегодня, возможно, благодаря развитию науки о данных и проектов с использованием искусственного интеллекта на предприятиях, вчера исполнилось 30 лет. Одним из пяти членов Руководящего совета Python 2021 года в рамках Python Software Foundation является Пабло Галиндо, инженер-программист Bloomberg, который говорил с VentureBeat о неотъемлемых проблемах, связанных с обеспечением роста и развития языка без ущерба для обратной совместимости.


Поднятые в интервью вопросы:


  1. Как Пабло начал работать с Python?
  2. Удивляет ли популярность Python?
  3. Каковы основные сценарии использования Python в Bloomberg?
  4. Какова оценка текущего уровня развития Python?
  5. Если бы Пабло мог принять любое решение о развитии Python, что бы он выбрал?
  6. Что Пабло сейчас знает такого, чего ему бы хотелось знать при начале работы?
  7. Что Пабло посоветовал бы руководителям организаций, которые внедряют Python?

Подробности [(en)]


Короткой строкой


Новости


Внедрения


110 тыс. лицензий ОС Альт приобрели государственные и коммерческие организации в 2020 г. []


Внутренние дела организаций


  1. Linux Foundation объявляет об избрании Хисао Мунаката из Renesas и Эрика Джонсона из GitLab в совет директоров[(en)]
  2. Linux Foundation и IBM поддерживают новые проекты с открытым исходным кодом для продвижения расовой справедливости [ 1(en), 2(en), 3(en)]
  3. LF Networking запускает проект с открытым исходным кодом Anuket, объединив CNTT (Cloud iNfrastructure Telco Taskforce) и OPNFV (Open Platform for Network Function Virtualization) [(en)]
  4. Lucid Sight приобретает движок для многопользовательской игры с открытым исходным кодом Colyseus [(en)]
  5. Еженедельник OSM 551 []
  6. Записи выступлений представителей Базальт СПО на Elbrus Tech Day []
  7. Astra Linux сертифицирована в Республике Беларусь []
  8. Интервью с экспертом. ОС Astra Linux: приоритет информационная безопасность пользователей []
  9. Алексей Смирнов рассказал на пресс-клубе РУССОФТа о тренде года переходе объектов КИИ на отечественные ОС Альт []

Ядро и дистрибутивы


  1. Пользователям AMD следует немедленно перейти на последнюю версию ядра Linux 5.11.[(en)]
  2. Началось альфа-тестироваине Slackware 15.0 []
  3. В ChromeOS теперь есть встроенная функция записи экрана [(en)]
  4. Chrome OS вышла на второе место по покупкам среди десктопных ОС [ 1, 2(en)]

Специальное


Apache Gobblin стал проектом верхнего уровня[(en)]


Мультимедиа


Краткий обзор готовящегося к выпуску VLC 4.0 взгляните на его новый интерфейс, находящийся в разработке[(en)]


Мобильные


  1. ВPinePhone решено поставлять по умолчанию Manjaro c KDE Plasma Mobile [ 1, 2, 3]
  2. Android 12 может наконец решить одну из самых неприятных проблем смартфонов, связанную с автоповоротом экрана[(en)]
  3. В Android 12 появился новый более простой способ обмена паролями Wi-Fi[(en)]
  4. Android 12 предлагает некоторые важные функции безопасности [(en)]
  5. Что нового в первой версии Android 12 Developer Preview [(en)]

Безопасность


  1. Инцидент со спамом Canonical после установки Ubuntu в облаке Azure []
  2. В Telegram обнаружено несколько серьёзных уязвимостей в системе безопасности[(en)]
  3. Новый плагин CrowdSec для защиты сайтов на WordPress []
  4. Уязвимость в DNS-сервере BIND, не исключающая удалённое выполнение кода []
  5. Серверы Windows и Linux были жертвами нового ботнета WatchDog почти два года[(en)]
  6. Эксплойт плагина WordPress подвергает риску более миллиона сайтов [(en)]
  7. Google занялся продвижением средств безопасной работы с памятью в открытом ПО [ 1, 2(en)]
  8. Уязвимость в Python, проявляющаяся при обработке непроверенных дробных чисел в ctypes []
  9. В Brave выявлена утечка через DNS сведений об открываемых в Tor-режиме onion-сайтах []

AI & Data Science


AWS присоединяется к PennyLane, платформе с открытым исходным кодом, сочетающей машинное обучение с квантовыми вычислениями.[(en)]


Web


  1. В DNS-сервер BIND добавлена экспериментальная поддержка DNS-over-HTTPS []
  2. Обновление Google Chrome может, наконец, сделать так чтобы браузер перестал загружать всю вашу оперативную память[(en)]

Для разработчиков


Доступен выпуск KDE Frameworks 5.79 []


Железо


Поскольку на Raspberry Pi Pico не встанет Linux, умелец портировал на плату Fuzix [ 1, 2(en)]


Статьи


Внутренние дела организаций


Facebook Magma набирает обороты под управлением Linux Foundation[(en)]


Ядро и дистрибутивы


Эмуляция сборки Red Hat Enterprise Linux на базе Fedora Rawhide []


Специальное


  1. Встречайте Plots: приложение для построения математических графиков для настольных компьютеров Linux[(en)]
  2. Защитите свой Home Assistant с помощью резервных копий [(en)]
  3. Разгоняем портал ДО на основе Moodle (решение проблем узких мест) []
  4. Установка Wine в Debian 10 []
  5. Руководство по TimeSynth библиотеке Python для генерации синтетических временных рядов[(en)]

Базы данных


  1. OrbitDB децентрализованная база данных на IPFS []
  2. Деплоим Tarantool без людей []
  3. Понимание баз данных с открытым исходным кодом[(en)]

Мультимедиа


5 обязательных медиаплееров для Linux[(en)]


DevOps


  1. Вертикальное автомасштабирование pod'ов в Kubernetes: полное руководство []
  2. Как Docker повышает безопасность и понятность для разработчиков[(en)]
  3. Первый взгляд на Tekton Pipelines []
  4. Разворачиваем кластер Kubernetes с помощью Kubernetes []
  5. 14 лучших практик разработки приложений на OpenShift []
  6. Мониторинг дисковой подсистемы VMware через CIM/Zabbix []
  7. 11 факапов PRO-уровня при внедрении Kubernetes и как их избежать []
  8. Настройка GitLab CI CD для Java приложения []
  9. KubeHelper упростите множество повседневных задач с Kubernetes через веб-интерфейс []

AI & Data Science


  1. Руководство по VISSL: Vision Library для самостоятельного обучения[(en)]
  2. Как классифицировать мусор с помощью Raspberry Pi и машинного обучения Arm NN []
  3. AI Weekly: проблемы создания наборов данных для обучения ИИ с открытым исходным кодом[(en)]

Web


  1. О 20-летии Drupal, одного из старейших проектов с открытым исходным кодом[(en)]
  2. Настройка PHP-FPM []
  3. Грабли WebRTC: как мы допиливали чужой велосипед []
  4. Неудобно использовать youtube-dl в Терминале? Есть альтернативы с графическим интерфейсом[(en)]

Для разработчиков


  1. Почему программисты любят пакетные менеджеры Linux[(en)]
  2. Хватит копировать, пора сливаться. Часть 1. Конфликт слияний []
  3. Хватит копировать, пора сливаться. Часть 2. Конфликт слияний, который так и не произошёл (а должен был) []
  4. Отлаживаем ядро из командной строки с bpftrace []
  5. Git для новичков (часть 2) []
  6. Можно ли написать один обработчик сразу для нескольких типов сообщений? И если нет, то как быть? []
  7. О поиске утечек памяти в С++/Qt приложениях []
  8. Рефакторинг пет проекта: докеризация, метрики, тесты []
  9. Зачем PVS-Studio использует анализ потока данных: по мотивам интересной ошибки в Open Asset Import Library []
  10. Об опыте Open Source стажировки в пандемию [(en)]
  11. В редакторе кода Visual Studio Code появилась поддержка Makefile []
  12. Как пользоваться gdb []

История


Как возник и вырос Ansible[(en)]


Пользовательское


  1. Что лучше: дистрибутив Linux в яблочном стиле или нормальный хакинтош? []
  2. Почему всем стоит попробоватьLinux [(en)]
  3. Как установить Linux в 3 шага [(en)]
  4. Что такое PPA Purge? Как использовать его в Ubuntu и других дистрибутивах на основе Debian? [(en)]
  5. Основы Bash-скриптинга для непрограммистов. Часть 3 []
  6. Загрузочный USB-накопитель с Linux для помощи пользователям Windows[(en)]
  7. 5 причин использовать менеджеры пакетов Linux [(en)]
  8. CentOS 7 и контроллер HPE B320i []
  9. 7 способов настройки рабочего стола Cinnamon в Linux [Руководство для начинающих][(en)]
  10. Starship: настраиваемое приглашение для любой командной оболочки [(en)]
  11. Что такое состояния процессов в Unix / Linux? [(en)]
  12. Раскройте скрытый потенциал Chromebook с помощью Linux [(en)]

Разное


  1. Дарите что-нибудь от души в общественное достояние[(en)]
  2. Установка Linux на калькулятор []
  3. Установка Linux на калькулятор. Часть II []

Релизы


Ядро и дистрибутивы


  1. Релиз ядра Linux 5.11[ 1, 2, 3]
  2. Выпуск дистрибутива Devuan 3.1, форка Debian без systemd [ 1, 2]
  3. Выпуск дистрибутива Siduction 2021.1 []
  4. Практическое руководство с Solus Linux 4.2: быстро установить и очень приятно использовать[(en)]
  5. Доступен Solaris 11.4 SRU30 []
  6. Выпуск дистрибутива Q4OS 3.14[ 1, 2]
  7. Выпуск минималистичного дистрибутива Tiny Core Linux 12 []
  8. Релиз дистрибутива для создания межсетевых экранов pfSense 2.5.0 []
  9. Компания Oracle выпустила ядро Unbreakable Enterprise Kernel R5U5 []

Специальное


  1. Cantera 2.5.1 []
  2. Выпуск DXVK 1.8, реализации Direct3D 9/10/11 поверх API Vulkan []
  3. Обновление драйвера Wayland для Wine []

Мультимедиа


  1. Выпуск открытой платформы виртуальной реальности Monado 21.0.0 []
  2. Релиз видео конвертера Cine Encoder 3.1 для работы с HDR видео в ОС Linux [ 1, 2]
  3. Kodi 19.0 []

Мобильные


Запуск бета-версии Android 12 9 важных изменений в вашем телефоне[(en)]


Безопасность


Обновление OpenSSL 1.1.1j, wolfSSL 4.7.0 и LibreSSL 3.2.4 []


DevOps


Kube-dump 1.0 []


AI & Data Science


Google выпускает Tensorflow 3D. Что это на самом деле?[(en)]


Web


  1. Выпуск новой стабильной ветки Tor 0.4.5 []
  2. Выпуск nginx 1.19.7, njs 0.5.1 и NGINX Unit 1.22.0 []

Для разработчиков


  1. Релиз проекта Dapr с открытым исходным кодом от Microsoft, предназначенного чтобы помочь разработчикам внедрять микросервисы [ 1(en), 2(en), 3(en)]
  2. Релиз языка программирования Haxe 4.2 []
  3. Racket 8.0 []
  4. Выпуск экспериментальной версии транслятора языка программирования Vala 0.51.1 []
  5. Релиз языка программирования Go 1.16 []
  6. Выпуск uefi-rs 0.8, обвязка для создания UEFI-приложений на языке Rust []
  7. Google анонсирует предварительную версию Android 12для разработчиков[ 1(en), 2(en), 3(en)]

Пользовательское


  1. Выпуск SANE 1.0.32 с поддержкой новых моделей сканеров []
  2. KDE Plasma 5.21. Новое Меню, Брандмауэр, Системный монитор, Новая тема [ 1, 2, 3]

Что ещё посмотреть


  1. Видеодайджест от сайта Пингвинус: Новая KDE Plasma 5.21. Релизы Ubuntu, LibreOffice 7.1, PaleMoon 29 []
  2. Проект недели по версии SD Times: GoReleaser [(en)]

Заключение


На этом всё, до следующего воскресенья!


Высказываю большое спасибо редакции и авторам OpenNET [], много новостных материалов и сообщений о новых релизах взято у них.


Если кто интересуется составлением дайджестов и имеет время и возможность помочь буду рад, пишите по контактам, указанным в моём профиле, или в личные сообщения.


Подписывайтесь на наш Telegram канал, группу ВКонтакте или RSS чтобы не пропустить новые выпуски FOSS News.


[] Предыдущий выпуск

Подробнее..

FOSS News 58 дайджест материалов о свободном и открытом ПО за 22-28 февраля 2021 года

28.02.2021 20:13:53 | Автор: admin

Всем привет!


Продолжаем дайджесты новостей и других материалов о свободном и открытом ПО и немного о железе. Всё самое главное про пингвинов и не только, в России и мире. Red Hat Enterprise Linux стал бесплатен для организаций, развивающих открытое ПО; Google профинансирует работу по повышению безопасности ядра Linux; на что соглашается человек, когда разрешает все куки; подъём Linux Foundation; интервью с Райаном Далем, создателем Node.js: Снижать сложность всегда полезно; Bedrock Linux: лего-набор для создания идеального linux-дистрибутива; использование быстрых клавиш в командной строке Linux и многое другое.


Оглавление


  1. Главное
    1. Red Hat Enterprise Linux стал бесплатен для организаций, развивающих открытое ПО
    2. Google профинансирует работу по повышению безопасности ядра Linux
    3. На что соглашается человек, когда разрешает все куки
    4. Подъём Linux Foundation
    5. Интервью с Райаном Далем, создателем Node.js: Снижать сложность всегда полезно
    6. Bedrock Linux: лего-набор для создания идеального linux-дистрибутива
    7. Использование быстрых клавиш в командной строке Linux
  2. Короткой строкой
    1. Новости
      1. Мероприятия
      2. Внедрения
      3. Открытие кода и данных
      4. Внутренние дела организаций
      5. Юридические вопросы
      6. Ядро и дистрибутивы
      7. Обучение
      8. Базы данных
      9. Мобильные
      10. Безопасность
      11. Web
      12. Для разработчиков
      13. Пользовательское
      14. Железо
      15. Разное
    2. Статьи
      1. DIY
      2. Ядро и дистрибутивы
      3. Специальное
      4. Мобильные
      5. Безопасность
      6. DevOps
      7. AI & Data Science
      8. Web
      9. Для разработчиков
      10. История
      11. Пользовательское
      12. Разное
    3. Релизы
      1. Ядро и дистрибутивы
      2. Системное
      3. Специальное
      4. Мультимедиа
      5. Безопасность
      6. DevOps
      7. Web
      8. Для разработчиков
      9. Пользовательское
      10. Игры
  3. Что ещё посмотреть
  4. Заключение

Главное


Red Hat Enterprise Linux стал бесплатен для организаций, развивающих открытое ПО


Категория: Новости/Ядро и дистрибутивы

OpenNET пишет: Компания Red Hat продолжила расширение программ по бесплатному использованию Red Hat Enterprise Linux, закрывающих потребности пользователей в традиционном CentOS, возникшие после трансформации проекта CentOS в CentOS Stream. В дополнение к ранее предоставленным бесплатным сборкам для рабочих внедрений (production), насчитывающих до 16 систем, предложена новая опция Red Hat Enterprise Linux (RHEL) for Open Source Infrastructure, которая позволяет без ограничений бесплатно использовать RHEL в инфраструктуре сообществ разработчиков открытых проектов и организаций, поддерживающих разработку открытого ПО. В частности, новая программа охватывает организации и проекты, вовлечённые в разработку и хостинг программного обеспечения, распространяемого под открытыми лицензиями, одобренными для включения в репозитории Fedora Linux. Бесплатное применение RHEL в подобных организациях разрешено в элементах инфраструктуры, таких как сборочные системы, системы непрерывной интеграции, почтовые и web-серверы. Участникам программы дополнительно предоставляется доступ к порталу Red Hat с документацией, базе знаний, форумам и системе аналитики Red Hat Insights. Формально сервис поддержки не охватывает участников RHEL for Open Source Infrastructure, но в зависимости от важности проекта компания Red Hat не исключает возможность предоставления бесплатной технической поддержки.


Подробности [ 1, 2, 3(en)]


Google профинансирует работу по повышению безопасности ядра Linux


Категория: Новости/Внутренние дела организаций

OpenNET пишет: Организация Linux Foundation объявила о предоставлении компанией Google финансирования работы по сопровождению механизмов защиты в ядре Linux и усилению безопасности ядра. В режиме полного рабочего дня будут трудоустроены Густаво Сильва (Gustavo Silva) и Натан Ченслор (Nathan Chancellor). Натан известен своей работой по обеспечению сборки ядра Linux с использованием компилятора Clang и задействованию при сборке механизмов защиты на этапе компиляции, таких как CFI (Control Flow Integrity). Густаво является одним из активных участников проекта KSPP (Kernel Self Protection Project) по продвижению в ядро Linux технологий активной защиты. .


Подробности [ 1, 2(en), 3(en), 4(en), 5(en), 6(en), 7(en)]


На что соглашается человек, когда разрешает все куки


Категория: Статьи/Юридические вопросы

Компания GlobalSign пишет в своём блоге на Хабре: Люди не читают инструкций. Вы почти наверняка не читали лицензионное соглашение Windows, не читали лицензионное соглашение iTunes, не читали условия Linux GPL или любого другого программного обеспечения. Это нормально. Такова наша природа. То же самое происходит в интернете. В последнее время благодаря GDPR и другим законам часто приходится видеть всплывающие сообщения, где вас спрашивают разрешения на использование cookies. Большинство нажимает Согласиться и продолжает жить как ни в чём ни бывало. Никто ведь не читает политику конфиденциальности, верно? Разработчик Конрад Акунга (Conrad Akunga) решил разобраться, какие конкретно условия предусмотрены соглашением об использовании. Для примера он взял новостной сайт Reuters.


Подробности []


Подъём Linux Foundation


Категория: Статьи/Внутренние дела организаций

Сегодня почти все в IT сфере знают про Linux, меньше про Linux Foundation, ещё меньше про положение дел у этого фонда и его историю. Кратко, но тем не менее, Analytics India Magazineзакрывает этот пробел и рассказывает об организации, ведущей более 100 проектов в целом ряде областей и создавшей код и другие продукты общей ценностью 54 миллиарда долларов.


Подробности [(en)]


Интервью с Райаном Далем, создателем Node.js: Снижать сложность всегда полезно


Категория: Статьи/Для разработчиков

Компания Evrone взяла интервью у основателя и первого разработчика Node.js и Deno Райана Даля: Нам предоставилась возможность поговорить с Райаном о его проектах. Он рассказал об основных задачах по развитию Deno, поделился мнением о будущем JavaScript и TypeScript, поведал о сторонних проектах экосистемы Deno и о том, как бы он изменил свой подход к Node.js, если бы мог путешествовать во времени.


Подробности []


Bedrock Linux: лего-набор для создания идеального linux-дистрибутива


Категория: Статьи/Ядро и дистрибутивы

Компания RUVDSпишет в своём блоге на Хабре: С момента появления Linux достаточно скоро возникло множество дистрибутивов: Slack, RedHat, Debian, SUSE и т. д. Тогда же возникла и проблема выбора дистрибутива, ведь каждый из них имеет свои особенности и преимущества, которые делают его особенным. RedHat и Debian наиболее стабильные и консервативные из дистрибутивов, Ubuntu заточен на удобство и имеет прекрасный пользовательский интерфейс, Gentoo свобода выбора и гибкость. У каждого пользователя Linux были моменты, когда ему не хватало некоторых функций, реализованных в других дистрибутивах. Создатели Bedrock Linux пошли дальше и создали полноценный мета-дистрибутив. В нем возможно использование не только пакетов, но и компонент различных Linux дистрибутивов, как кубиков Лего. В одном окружении можно создать систему из нескольких Linux OS, например установку дополнительных пакетов Ubuntu поверх базовых компонент Debian и Arch.


Подробности []


Использование быстрых клавиш в командной строке Linux


Категория: Статьи/Пользовательское

ГК ЛАНИТразместила в своём блоге на Хабре статью, посвященную наиболее часто используемым комбинациям клавиш при работе в командной строке Linux (в основном в командном интерпретаторе bash). По словам автора, статья точно будет полезна начинающим своё знакомство с Linux и пригодится тем, кто уже имеет опыт. Прерывание выполнения команды, окончание ввода файла, отправка процесса в фон, очистка экрана, поиск по истории, автодополнение различных видов вот некоторые примеры описанных сочетаний клавиш.


Подробности []


Короткой строкой


Новости


Мероприятия


  1. Вебинар Ошибки PRO-уровня при внедрении Kubernetes []
  2. Linux Foundation, LF Networking и LF Edge объявляют список спикеров на форуме руководителей Open Networking & Edge, 10-12 марта[(en)]
  3. Bебинар Автоматизация процессов с GitLab CI/CD []
  4. Akademy 2021 пройдёт онлайн с 18 по 25 июня []
  5. Linux App Summit 2021 состоится в виртуальном формате с 13 по 15 мая []

Внедрения


Агентство NASA использовало Linux и открытое ПО в марсолёте Ingenuity [ 1, 2]


Открытие кода и данных


  1. Программа для организации потокового вещания msd открыта под лицензией BSD []
  2. Инструмент для 3D печати CEL Automaker выпущен под открытой лицензией [(en)]
  3. Microsoft открыла код инструмента для поиска следов Solarigate [(en)]

Внутренние дела организаций


  1. Программное обеспечение Red Hat теперь доступно на IBM Power Systems[ 1(en), 2(en)]
  2. Red Hat завершает приобретение системы безопасности Kubernetes StackRox [ 1(en), 2(en)]
  3. Linux Foundation объявляет о создании DizmeID Foundation для разработки и включения сети учетных данных SSI (Self-sovereign Identity) [(en)]
  4. Google начала спонсировать двух разработчиков ядра Linux []
  5. Проект Debian запустил сервис для динамического получения отладочной информации []
  6. GitHub опубликовал отчёт о блокировках в 2020 году [ 1, 2]
  7. Canonical повысит качество промежуточных LTS-выпусков Ubuntu []
  8. Компания Mozilla опровергла ложную информацию об удалении лисы с логотипа Firefox [ 1, 2]
  9. Еженедельник OSM 552 []
  10. Компания Slimbook стала спонсором KDE []

Юридические вопросы


  1. Репозиторий проекта RE3 заблокирован на GitHub []
  2. 4 новых Open Source лицензии licenses [(en)]

Ядро и дистрибутивы


В OpenBSD добавлена начальная поддержка чипа Apple M1 [ 1, 2]


Обучение


  1. Доступны бесплатные уроки видеокурса по Apache Kafka []
  2. Яндекс.Практикум запустил курс React-разработчик []

Базы данных


Google Cloud расширяет партнерство с MongoDB, чтобы помочь клиентам ускорить модернизацию приложений[(en)]


Мобильные


  1. Российский разработчик написал клиент Clubhouse для Android после реверс-инжиниринга API [ 1, 2]
  2. Первая предварительная версия Android 12 включает новые инструменты для улучшения взаимодействия с пользователем[(en)]
  3. Новости Android разработки 23.02.2021 []
  4. Последнее обновление Android позволит вам планировать отправку сообщений, улучшить защиту паролей и многое другое[ 1(en), 2(en)]

Безопасность


  1. Telegram в Windows 10 получает серьезное улучшение безопасности[(en)]
  2. Обновление Python исправляет несколько серьезных проблем безопасности [(en)]
  3. Уязвимости во FreeBSD, позволяющие обойти ограничения jail-окружений []
  4. GitHub CSO обещает больше инструментов безопасности и функций для разработчиков [(en)]

Web


  1. Chrome скоро может унаследовать один из лучших инструментов от Google Reader[(en)]
  2. Браузер Brave скоро поможет вам покупать криптовалюту по самой выгодной цене [(en)]
  3. Разработчики Firefox закрыли тикет 17-летней давности []
  4. В Chrome экспериментируют с открытием сайтов по умолчанию через HTTPS []

Для разработчиков


  1. Языку Python исполнилось 30 лет []
  2. GitHub документировал механизм блокировки всей сети форков []

Пользовательское


Разработчики Linux Mint обращаются к пользователям: прекратите использовать устаревшие версии, обновите программное обеспечение сейчас[(en)]


Железо


Запуск клавиатуры с открытым исходным кодом; System76 опубликовала свои файлы дизайна[(en)]


Разное


  1. Коммерческую систему компьютерных шахмат Fat Fritz 2 уличили в плагиате движка open source []
  2. Обратная сторона Open Source-славы: как угрожают автору curl []

Статьи


DIY


Приглашаю к созданию русской народной игры Колобок []


Ядро и дистрибутивы


  1. Как мы раскрыли 24-летний баг в ядре Linux []
  2. Знакомство с KaOS Linux независимым дистрибутивом KDE Plasma Desktop[(en)]

Специальное


  1. Об использовании Wine для запуска Windows приложений в Linux[(en)]
  2. ESPlot: программное обеспечение с открытым исходным кодом для построения высокочастотных данных в реальном времени для встраиваемых систем [(en)]
  3. Лучшие аналоги Visio для Linux []
  4. MyCompany открытая платформа для автоматизации бизнес-процессов малых предприятий []
  5. Почему Linux так важен для Edge вычислений[(en)]
  6. Руководство по Pastas, среде Python для анализа гидрогеологических временных рядов [(en)]
  7. О том как встретились 3D-печать с открытым исходным кодом и гонки на симуляторах [(en)]

Мобильные


Мануал по настройке стандартного эквалайзера Android для самых маленьких (и не только) []


Безопасность


Поддержка токенов PKCS#11 с ГОСТ-криптографией в Python []


DevOps


  1. Создание пайплайнов CI с помощью Tekton (внутри Kubernetes). Часть 1/2 []
  2. Создание пайплайнов CI с помощью Tekton (внутри Kubernetes). Часть 2/2 []
  3. Продолжаем прокачивать Ansible []
  4. Пошаговое руководство по событиям в Knative[(en)]
  5. KubeEdge: надежное соединение между облаком и Edge [(en)]
  6. AD + Freeradius + Google Autheticator. Установка с нуля для Cisco Anyconnect и не только []
  7. Почему язык Go стал стандартом для DevOps-инженеров []
  8. Kubernetes это как океанариум []
  9. О том как стать мейнтейнером Kubernetes тратя 4 часа в неделю[(en)]
  10. Argo CD: готов к труду и обороне в Kubernetes []

AI & Data Science


  1. Руководство по Pyro глубоко вероятностному языку программирования[(en)]
  2. Google представляет Model Search, платформу с открытым исходным кодом для автоматического поиска оптимальных моделей машинного обучения [(en)]
  3. Практическое руководство по Model Search: платформа на основе Tensorflow для AutoML [(en)]
  4. 10 лучших библиотек оптимизации гиперпараметров с открытым исходным кодом для моделей машинного обучения [(en)]
  5. Программируемые NER компоненты []
  6. Руководство по MBIRL модели обучения с обратным подкреплением[(en)]

Web


  1. Как запустить сервер разработки для веб-приложений Flask с помощью Google Colab[(en)]
  2. Альтернатива электронной почте для 21 века []
  3. Как устроена фильтрация спама в Zimbra []
  4. Что вам нужно знать, если вы поменяете nginx на envoy: впечатления спустя два года []

Для разработчиков


  1. Обзор последних изменений в rotor'е (v0.10 v0.14) []
  2. Путешествие в unmanaged code: туда и обратно []
  3. Часто встречающиеся ошибки разработки сетевого взаимодействия []
  4. Состояние разработки программного обеспечения Java в 2021 году[(en)]
  5. Руководство по виртуальным средам Python с virtualenvwrapper [(en)]
  6. Спецификация D-Bus. Часть 2, заключительная []
  7. Free Heroes of might and magic 2 open-source проект, в котором хочется участвовать []
  8. 6 лучших библиотек визуализации данных в Golang[(en)]
  9. 5 причин, по которым я люблю программировать в Linux []
  10. Как установить последнюю версию Erlang в Ubuntu Linux[(en)]
  11. Учим HostBinding работать с Observable []

История


Заметки о Unix: история Unix до readline []


Пользовательское


  1. Linux, suspend to RAM и ИБП []
  2. 5 преимуществ выбора Linux[(en)]
  3. Проверьте использование вашего диска с помощью терминала duf [удобная альтернатива командам du и df] [(en)]
  4. Что делает сообщество Linux особенным? [(en)]
  5. Об установлении пути в FreeDOS [(en)]
  6. О навигации в FreeDOS [(en)]
  7. Как удалить snap пакет []
  8. Об использовании команды anacron в Linux[(en)]
  9. Создание deb пакетов []
  10. 3 Linux терминала, которые стоит попробовать [(en)]

Разное


  1. Обнаружена пасхалка в GNOME []
  2. Окопипасте про GNU и Linux [(en)]
  3. О построении своих технологий на основе [(en)]

Релизы


Ядро и дистрибутивы


  1. Доступны новые установочные сборки Void Linux []
  2. Релиз дистрибутива для исследования безопасности Kali Linux 2021.1 [ 1, 2, 3(en)]
  3. Выпуск дистрибутива Mageia 8, форка Mandriva Linux [ 1, 2]

Системное


  1. Выпуск пакетного менеджера APT 2.2 []
  2. Выпуск системы инициализации sysvinit 2.99 []
  3. Выпуск глобальной децентрализованной файловой системы IPFS 0.8 []
  4. Релиз распределенного реплицируемого блочного устройства DRBD 9.1.0 []

Специальное


  1. Новая версия Wine Launcher 1.4.46 инструмента для запуска Windows игр через Wine []
  2. Релиз платформы OroPlatform 4.2.1 LTS, а также приложений OroCommerce и OroCRM []
  3. Релиз FreeRDP 2.3, свободной реализации протокола RDP []
  4. Выпуск Wine 6.3 []

Мультимедиа


  1. Релиз открытого медиацентра Kodi 19.0 []
  2. Релиз MPD-клиента Ymuse 0.17 []

Безопасность


Выпуск passwdqc 2.0.0 с поддержкой внешних фильтров [ 1, 2]


DevOps


Red Hat открывает путь как для виртуальных машин, так и для контейнеров в своем последнем выпуске OpenShift 4.7[ 1(en), 2(en), 3(en)]


Web


  1. Выпуск платформы для организации совместной работы Nextcloud Hub 21 [ 1, 2(en)]
  2. Релиз Firefox 86 [ 1, 2, 3, 4, 5(en), 6(en), 7(en)]
  3. Выпуск Tor Browser 10.0.12 и дистрибутив Tails 4.16 []
  4. Проект Tor опубликовал приложение для обмена файлами OnionShare 2.3 []
  5. Выпуск NeoChat 1.1 []

Для разработчиков


  1. Релиз языка nim 1.4.4 []
  2. Вышел релиз GitLab 13.8 с редактором конвейеров и первой из метрик DORA []
  3. Granulate запускает платформу с открытым исходным кодом G-Profiler[(en)]

Пользовательское


  1. Корректирующий релиз GNOME 3.38.4 []
  2. Релиз сетевого конфигуратора NetworkManager 1.30.0 [ 1, 2]
  3. Драйверы HPLIP 3.21.2 с поддержкой новых принтеров. Поддержка Fedora 33, Manjaro 20.2 []
  4. Опубликован корректирующий выпуск Plasma 5.21.1 []

Игры


Доступна двадцать четвёртая альфа-версия открытой игры 0 A.D. [ 1, 2, 3]


Что ещё посмотреть


  1. Дайджест от Red Hat: поваренная книга Quarkus Cookbook, бесплатный Developer Sandbox for OpenShift и руководство CentOS Project []
  2. Open Source проект недели по версии SD Times: PennyLane [(en)]

Заключение


На этом всё, до следующего воскресенья!


Высказываю большое спасибо редакции и авторам OpenNET [], много новостных материалов и сообщений о новых релизах взято у них.


Если кто интересуется составлением дайджестов и имеет время и возможность помочь буду рад, пишите по контактам, указанным в моём профиле, или в личные сообщения.


Подписывайтесь на наш Telegram канал, группу ВКонтакте или RSS чтобы не пропустить новые выпуски FOSS News.


[] Предыдущий выпуск

Подробнее..

Поваренная книга Quarkus Cookbook, бесплатный Developer Sandbox for OpenShift и руководство CentOS Project

25.02.2021 12:15:55 | Автор: admin

Мы собрали для вас короткий дайджест полезных материалов, найденных нами в сети за последние две недели. Оставайтесь с нами станьте частью DevNation!

Начни новое:

Качай:

  • Бесплатный Developer Sandbox for OpenShift
    Это ваш личный OpenShift в облаке, всего за пару минут и без какой бы то ни было инсталляции. Среда создана специально для разработчиков и включает в себя Helm-диаграммы, builder-образы Red Hat, инструменты сборки s2i, также CodeReady Workspaces, облачную IDE с веб-интерфейсом.

Мероприятия:

Подробнее..

Мануал по настройке стандартного эквалайзера Android для самых маленьких (и не только)

26.02.2021 14:22:55 | Автор: admin

Warning!
Тут не будет очень глубокого разбора частот, волн и низкоуровневого преобразования звука. Это статья для тех, кто хочет быстро и максимально понятно, разобраться в эквалайзере. Объясняю практически на пальцах.

Немного теории перед тем как начнем.

Битрейт (bitrate)(kbps)
Чем выше битрейт файла, тем качественнее звук, и тем больше места файл занимает на диске.

Форматы:
1.Без сжатия, такие как (WAV, AIFF)
2.С сжатием без потерь качества (APE, FLAC)
3.С сжатием и с потерей качества (MP3, Ogg)

До знакомства с обработкой звука, я принимал звук как данность, вне зависимости от качества. Будь-то .mp3 с битрейтом 92 kbps или .wave c битрейтом 320 kbps. Однако почитав много статей на хабре и прочих обучающих сайтах, я понял, что это не только интересно и полезно.

Самое важно при работе со звуком - это СЛУШАТЬ!
Возникает резонный вопрос "В смысле "слушать", а что я по твоему делаю?"
Звук для каждого человека индивидуален. Можно дать одну песню 10 людям и для каждого она будет звучать по разному.Кто-то лучше воспринимает высокие частоты, кто-то любит когда много баса, кто-то может выкрутить неимоверные значения на эквалайзере и получать удовольствие от нестандартного звучания.
Всегда настраивайте звуковое оборудование(колонки,subwoofer, наушники и т.д.) ПОД СЕБЯ и на СВОЙ ВКУС.

Вернемся к эквалайзеру.

Для начала хочу начать с того, что далеко не все используют настройки эквалайзера.

На то есть несколько причин:
1.Наличие дорогих наушников с отличным звуком. (скажем от 100$)
2.Не привередливость к качеству звука и звучанию музыки в целом.
3.Многим просто лень копаться в непонятных полосках и просто смеряются с качеством звука.

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

Первой ползунок в 60Hz отвечает за Bass (бас).

Думаю тут не надо долго объяснять, что повышение или понижение значения увеличивает или уменьшает объем баса соответственно. (спасибо Кэп).

Второй ползунок 230Hz
Он отвечает за глубину и объемность звучания и отчасти за задний план(instrumental).

Повышение или понижение значения, добавляет или уменьшает объемность звука соответственно.

Третий ползунок 910Hz
Он отвечает за дальность или громкость вокала и за шумность заднего плана.

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

Четвертые ползунок 4kHz
Это смежный параметр между 910hz и 14kHz т.к при повышении значения улучшается чистота и резкость звучания и увеличивает эффект приближения вокала и придает вокалу более чистое и мягкое звучание.

Пятый ползунок 14kHz
Отвечает за громкость, резкость и чистоту звука.

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

Так, остались еще 2 ползунка. Да нижние. Тут все обстоит куда проще.

Bass boost - это всем известный бас. Просто если нужно Больше баса, чтобы можно было "просто брать и обмазываться" басом.

Surround Sound - это объёмный звук, нужный для увеличения пространственного звукового эффекта, путем создания акустической атмосферы в ограниченном пространстве комнаты или другого помещения или звука в общем.

Сам же я пользуюсь бюджетными наушниками Panasonic rp-djs150.
И специально подобранным пресетом эквалайзера для них.
Учтите, что для разных наушников, нужны разные варианты настройки частот.

В процессе идет подготовка статьи с полным разбором 10-ти полосного эквалайзера Viper4android. Ссылка будет вот Тут.

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

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

Надеюсь моя статья поможет вам и привнесет новые эмоции при прослушивании любимых песен.

Подробнее..

14 лучших практик разработки приложений на OpenShift

18.02.2021 14:23:54 | Автор: admin

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

Надежность приложений

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

1. Не храните конфигурацию приложения внутри контейнера

Если контейнерный образ содержит конфигурацию для какой-то конкретной среды (Dev, QA, Prod), его не получится без изменений переносить между средами. Это плохо с точки зрения надежности процесса выпуска версий, поскольку в продакшн пойдет уже не тот образ, который тестировался на предыдущих этапах. Поэтому не держите внутри контейнера конфигурацию приложения для конкретной среды, а храните ее отдельно, например, с помощью ConfigMaps и Secrets.

2. Задавайте ресурсные требования и лимиты в определениях podа

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

3. Прописывайте зонды активности (liveness) и готовности (readiness) в определениях podа

С помощью этих зондов кластер может обеспечивать базовую устойчивость: перезапускать приложение, если не проходит liveness, или больше не маршрутизировать на него трафик, когда не отвечает readiness. Подробнее см. раздел Мониторинг работоспособности приложений в документации OpenShift Platform.

4. Используйте PodDisruptionBudget для защиты приложений

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

5. Правильное завершение работы podов

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

6. Один контейнер один процесс

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

7. Используйте системы мониторинга приложений и оповещения

Мониторинг приложений средствами Prometheus и Grafana помогает поддерживать нормальную работу приложений в продакшн-режиме согласно требованиям бизнеса.

8. Пусть приложения пишут свои логи в stdout/stderr

Тогда OpenShift сможет собирать и пересылать их в централизованную систему обработки (ELK, Splunk). Логи это бесценный ресурс при анализе работы приложения в продакшн-режиме. Кроме того, оповещения, генерируемые на базе содержимого логов, помогают проконтролировать, что приложение работает как задумано.

9. Изучите целесообразность применения Circuit breakers, Timeouts, Retries, Rate Limiting

Эти механизмы повышают устойчивость приложения к отказам, защищая от перегрузок (Rate Limiting, Circuit Breakers) и помогая справляться с сетевыми проблемами (Timeouts, Retries). Рассмотрите возможность применения решения OpenShift Service Mesh, которое позволяет реализовать эти функции, не трогая код приложений.

Безопасность приложений

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

10. Используйте только доверенные контейнерные образы

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

11. Используйте последние версии базовых контейнерных образов

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

12. build-образы отдельно, runtime-образы отдельно

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

13. Restricted security context constraint (SCC) везде, где только возможно

Модифицируйте образы, чтобы они могли работать в рамках restricted SCC (подробнее см. раздел Поддержка произвольных идентификаторов пользователей в документации). Риски взлома приложений включают в себя и ситуации, когда злоумышленник получает контроль над самим приложением, и restricted SCC позволяет обезопасить узел кластера на этот случай.

14. TLS для защиты коммуникаций между компонентами приложения

Компоненты приложения могут пересылать друг другу конфиденциальные данные. Если сеть, в которой работает OpenShift, не может считаться безопасной, то трафик между компонентами приложения можно защитить с помощью TLS-шифрования, а уже упомянутый OpenShift Service Mesh позволяет сделать это, не трогая код приложений.

Заключение

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

Подробнее..

Сборка Open Source GTA VC и GTA III в Linux

17.02.2021 22:18:17 | Автор: admin
image
Скорее всего нет тут такого человека, который бы не играл в GTA (или хотя бы не слышал о ней). Первая 3D версия серии вышла около 20 лет назад. Это была GTA III. Через год вышла GTA: Vice City. Несмотря на это, в эти игры до сих пор не только играют, но и создают моды. Эти игры портированы на множество платформ, но к сожалению, Linux (до недавнего времени) обошли стороной. Единственный вариант поиграть в Linux был wine. Но недавно все изменилось.

Мне на глаза новость Разработчики закончили реверс-инжиниринг GTA III и Vice City и выпустили порты для разных платформ. А так как я слежу за всем, что касается исходников(утечки, открытие и т.д.), а также люблю собирать софт из исходников разумеется это я не мог проигнорировать. Из новости я понял, что энтузиасты опубликовали исходный код GTA III и GTA: VC. Моей радости не было предела. Я сразу же пошел на github за дополнительной информацией.

Основные улучшения (касательно miami):
Исправлено множество мелких и крупных багов.
Пользовательские файлы (сохранения и настройки), теперь хранятся в корневом каталоге GTA.
Настройки теперь хранятся в файле reVC.ini (в оригинале были в gta_vc.set).
Добавлено меню отладки (доступно по CTRL+M).
Свободная камера (Debug camera). CTRL+B вкл/выкл. При включении камеру можно свободно перемещать во всей карте.
Убраны экраны загрузки между островами.
И некоторые другие исправления/улучшения, включая исправления для других платформ.
Примечание: эти параметры можно настроить в файле core/config.h. Некоторые параметры можно менять прямо в игре (используя отладочное меню), а для остальных потребуется пересборка.

Перейдем к самому интересному, а именно к сборке miami (GTA: VC).
Нам потребуются:
Дистрибутив Linux (Ubuntu, Debian, Mint, etc);
Оригинальные файлы (ассеты) с дистрибутива игры VC (в случае сборки GTA III соответственно потребуются файлы GTA III).
GCC.
Некоторые библиотеки и заголовочные файлы.

В качестве ОС использую Linux Mint 19.3 (основа Ubuntu 18.04 LTS). Установить компиляторы gcc можно так (если не установлены):
sudo apt install build-essential

Установка необходимых библиотек:
sudo apt install libopenal-dev libglew-dev libglfw3-dev libmpg123-dev

Тут остановимся и рассмотрим поподробнее. Я вчера пол часа потратил на поиск решения проблемы компиляции из-за своей невнимательности. На GitHub четко указано, что версия библиотеки glfw должна быть не ниже 3.3, в то время как в репозиториях Ubuntu 18.04 3.2. Поэтому, если у вас дистрибутив построенный на Ubuntu 18.04 (или в репозитории версия библиотеки glfw ниже 3.3) то данную библиотеку необходимо собрать из исходников. Но тут нет ничего сложного. Качаем архив github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.zip
Распаковываем в любую папку. Заходим в распакованную папку и выполняем следующие команды:
mkdir glfw-buildcd glfw-buildcmake -DBUILD_SHARED_LIBS=ON ../make -j2sudo checkinstall

Библиотека нужной версии установлена. Теперь клонируем репозиторий:
git clone --recursive -b miami https://github.com/GTAmodding/re3.git reVC

Это много времени не займет. После клонирования размер папки reVC около 120 МБ(из которых 70 МБ папка .git).
Далее идем в папку reVC и запускаем premake5Linux:
./premake5Linux --with-librw gmake2

Генерация фалов сборки займет пару секунд.
Примечание: Если вы используете архитектуру arm/arm64 то вам нужно собрать утилиту premake5Linux из исходников, а потом запустить с параметром, указанном выше.

Теперь собственно сама сборка. Для сборки доступны следующие конфигурации:
debug_linux-x86-librw_gl3_glfw-oal
debug_linux-amd64-librw_gl3_glfw-oal
debug_linux-arm-librw_gl3_glfw-oal
debug_linux-arm64-librw_gl3_glfw-oal
release_linux-x86-librw_gl3_glfw-oal
release_linux-amd64-librw_gl3_glfw-oal
release_linux-arm-librw_gl3_glfw-oal
release_linux-arm64-librw_gl3_glfw-oal

Думаю, из названий и так все понятно. Главное не перепутайте amd64 и arm64(я вчера ночью сонный недосмотрел, потом не мог понять, почему не происходит сборка).
Переходим в директорию reVC/build и запускаем make с вашей конфигурацией. В случае с debug-версией для amd64 нужно так:
make config=debug_linux-amd64-librw_gl3_glfw-oal

Компиляция происходит достаточно быстро. На моём старом ноутбуке (Asus X55A, Pentium B970 2x2.3 ГГц и 4 Гб памяти) сборка отладочной версии заняла 2 мин. 10 сек.(выходной файл = 30.4 МБ), релизной 4 мин. 44 сек.(размер файла = 43,8 МБ). По своему опыту скажу, что во многих случаях обычно все наоборот.

Если компиляция прошла без ошибок, то в папке reVC/bin/ваша_конфигурация/Debug_или_Release/ будет бинарник reVC.

Копируем куда-нибудь оригинальную папку с GTA: VC (при желании, можно удалить все файлы из корня они нам не понадобятся). Потом в папку с игрой копируем наш бинарник reVC. Теоретически, игру уже можно запускать, и даже играть. Но текст на некоторых пунктах меню будут неправильно отображаться:
image
Чтобы это исправить, копируем папки с заменой из reVC/gamefiles в папку с игрой. Правда, в таком случае, игра будет на английском языке.

Теперь пробежимся по меню отладки:
image

Что бы включить или выключить меню отладки нажмите CTRL+M.
Cam все, что связанно с камерой.
Cheats Различные читы.
Debug Отображение разной отладочной информации, позиции игрока, и т.д.
Debug Render Можно скрывать или отображать различные объекты, транспорт, строения, пешеходов, показывать пути транспорта и пешеходов и т.д.
Game Телепортация в любое место (предварительно нужно поставить метку на карте). Также можно запустить абсолютно любую миссию.
Particle Не знаю что это такое.
Render Некоторые fix'ы, настройка fps, графические настройки
Spawn Спаун транспорта.
Time & Weather Настройка времени и погоды.

Сборка GTA III ничем не отличается, за исключением клонирования репозитория:
git clone --recursive https://github.com/GTAmodding/re3.git


Насчет модов: текстуры, скрипты, модели должны работать. А вот dll/asi, CLEO работать не будут. Некоторые возможности этих модов уже реализованы в re3, некоторые можно настроить в файле config.h.

Ссылки по теме:
github.com/GTAmodding/re3
Инструкция по сборке GTA III
Готовые бинарники reVC для Mac, Linux, Windows
Готовые бинарники re3 для Mac, Linux, Windows
Просмотр репозитория в Visual Studio Code
Lifehack: Если в ссылке на github изменить github.com на github1s.com, то репозиторий можно просматривать в удобном Visual Studio Code.
Подробнее..

Категории

Последние комментарии

© 2006-2021, personeltest.ru