Telegram Web Link
Познакомился с занятным инструментом для рисования графиков в документации к коду не выходя из гита. Самый простой способ что-то написать про проект - вписать это в Readme в формате markdown. У этого формата есть расширение для формирования иллюстраций - Mermaid.

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

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

Раньше я делал схемы и иллюстрации к проектам как завещали деды учили в универе: открываем inkscape и рисуем векторную картинку. С новым для меня инструментом все стало в разы быстрее. А в дополнение мы получаем все плюшки гита: версионирование и лог всех изменений с возможностью быстрого отката на старые версии.

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

flowchart TD
mainDb[(PostgreSQL)]
botDb[(PostgreSQL)]
api[API]
service[Worker Service]
botService[Telegram Bot]
broker[[RabbitMQ]]
frontend[Frontend]

botService --> botDb
api ---> mainDb
service ---> mainDb
frontend --"REST"--> api ---> broker --> service
service ---> broker
botService ---> broker
broker ---> botService


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

P.S. Из забавного - в гите не предусмотрели возможности скопировать диаграмму отдельно как картинку.
Sphagnum. Часть 8. Фиксация концепции.
#sphagnum@eshu_coding

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

А пока хочу изложить несколько концепций, которые ложатся в основу проекта.

1.  Создаю гибрид Apache Kafka и RabbitMQ. Логика организации маршрутизации сообщений будет такова:
Exchange и очереди, как в RabbitMQ, с ключами маршрутизации (Routing key). Пока планирую два вида Exchange - один отдает сообщения во все очереди с соответствующим ключем, второй - в одну, выбранную случайным образом. При этом, Exchange хранит всю прокачанную историю сообщений, как это делает Кафка.

2. Данные бэкапятся на диск в виде WAL. Скорее всего будут жить страницами минимум по 4Кб, если сообщение туда влезает. Если нет - отдельная страница для отдельного сообщения.

3. Очередь хранит в себе номер страницы WAL и id сообщения. Хочу попробовать сделать два вида очередей: классическую FIFO и стек - LIFO.

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

5. Алгоритм выборов нового мастера внутри кластера в случае падения пока мне видится следующим:
a) При синхронной репликации выбирается наименее проблемный инстанс.
b) При асинхронной - наименее проблемный из имеющих последнюю версию данных.
Конфликты, когда все параметры кандидатов одинаковы решаются жребием:)

Со временем планирую добавить горизонтальную масштабируемость, но пока по ней есть только сырые идеи.
Forwarded from Варфоломеевы дневники (Andrey Varfolomeev)
Я нечасто прошу о помощи, но сейчас вынужден обращаться буквально ко всем.

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

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

Пожалуйста, если не вас затруднит:

1. Перейдите по ссылкам этой статьи, прочитайте, чтобы был просмотр, и оставьте лайк/комментарий.

На VC
https://vc.ru/u/1241162-andrey-varfolomeev/1054930-mo..

На Пикабу
https://pikabu.ru/story/moyu_semyu_lishayut_imushchestva_v_god_semi_chtobyi_oplatit_chuzhie_dolgi_11180949

2. Лайк/репост/комментарий этого поста во Вконтакте

https://vk.com/varfolomeevandrey?w=wall412460093_145

Заранее всех очень сильно благодарю!
Вышло очень хорошее описание потокобезопасных коллекций в c#.

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

#csharp
Познал дзен написания автотестов в c#. Тесты я пишу уже довольно давно и помногу, но во основном функциональные/интеграционные, закрывающие функционал проекта в целом. При этом зависел я обычно только от объектов инфраструктуры: баз данных, брокеров сообщений и т.д. Модульные тесты тоже писал, но только на места с неочевидной сложной логикой, которая не помещается в голове.

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

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

До недавнего времени я пилил эту реализацию сам, но тут проникся двумя инструментами - NSubstitute и Autofixture. Первый позволяет создавать фейковые реализации, второй - инициализировать инстансы классов для возвратов с заполненными полями.

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

Autofixture мне не казалось чем-то нужным, до тех пор, пока мне не пришлось тестировать проброс информации из глубинных слоев наверх, с возвращаемой моделью (в сумме с вложенными классами) в пару тысяч строк. Говоришь: мне нужен объект, поля id, name, userid должны иметь заданные значения. Остальные - заполнятся по усмотрению библиотеки чем-то не-дефолтным. Раз - и объект для теста готов, без бесконечной лапши с инициализацией полей руками.

#csharp
#tests
Sphagnum. Часть 9. Доска задач и репозиторий.
#sphagnum@eshu_coding

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

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

Затем я подумал о Гитлабе. Весь нужный функционал есть, но вспомнил, сколько мороки с администрированием и настройкой и расхотел.

Зашёл на гитхаб - ux не очень. Быстро (в течение 2 минут) сделать минималистичный канбан в проекте не удалось.

Тогда я решил причаститься Gitea. Доска конкретного репозитория создалась за минуту, коммиты прилинковались, чек листы в задачах удобные. Зеркалирование на гитхаб настроилось мгновенно.

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

#gitea
#cicd
#devops
Освоил девопсячий минимум на базе Gitea. В целом - тот же gitlab, но без понтов и ощутимо проще.

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

Вставляем кусок yml скрипта из примера в папку для ci cd скриптов - управление командной строкой работает. Если гитлаб раннер может выполняться миллионом разных способов: и в докере, и в командной строке самой машины и ещё хрен знает как, тот у act_runner-а - раннера gitea - вариант один - в докер контейнере с node.js.

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

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

#gitea
#devops
Продолжая тему модульных тестов в c#. Вляпался в занятную ситуацию с Autofixture. Строки и числа Autofixture заполняет случайными значениями, меняющимися от запуска тестов к запуску. А вот тот момент, что значения булевых полей меняются по другим законам я как-то упустил.

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

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

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

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

#csharp
#tests
Forwarded from .NET epeshk blog
pl/dotnet

Для PostgreSQL появилась поддержка C# и F# как языков процедур.

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


CREATE OR REPLACE FUNCTION dynamic_record_generator_srf(lim INT8)
RETURNS SETOF record
AS $$
upperLimit = lim.HasValue ? lim : System.Int32.MaxValue;
for(long i=0;i<upperLimit;i++){ yield return new object?[] { i, $"Number is {i}" }; }
$$ LANGUAGE plcsharp;

CREATE OR REPLACE FUNCTION dynamic_record_generator_srf_fsharp(lim INT8)
RETURNS SETOF record
AS $$
let upperLimit = Option.defaultValue (int64 System.Int32.MaxValue) lim
seq { for i in 0L .. upperLimit - 1L do yield [| box i; $"Number is {i}" |] }
$$ LANGUAGE plfsharp;

https://www.postgresql.org/about/news/announcing-pldotnet-version-099-beta-2838/

https://github.com/Brick-Abode/pldotnet/wiki/pldotnet:-White-Paper

А о релизе интеграции я узнал из канала @vchirikov

@epeshkblog | Поддержать канал
Если используете десктопный клиент телеги на Винде - обновитесь - там феерическая дыра обнаружилась. Для браузера/линуха не актуально.

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

Вчера пришла идея - было бы неплохо управлять ютубом с телефона. Нужны включение нового видео и постановка на паузу. Прикинул решение - самым простым показалось использование использование телеграм бота в качестве виндовой службы, управляющей браузером через PowerShell. В можно было бы вспомнить/изучить нативную виндовую часть c# и сделать все по фен-шую, но желания не было от слова совсем. В итоге для отправки в браузер горячих клавиш Ютуба - F (полный экран) и K (пауза) - бот запускает скрипт PowerShell из строковой переменной:)

Какая там разработка банковского ПО или СППВР! Вот - настоящая магия, приносящая удовлетворение: три часа и получившийся мутант запущен в качестве консольного приложения. Осталось спрятать окно так, чтобы не мозолило глаза...

После 6 часов мучений я узнал что надо внимательно читать мануалы. А кроме того, ряд нюансов по написанию виндовых служб на современном c#:
1. Чтобы запускать обычный шарповый серверный проект в качестве службы надо дополнительно ставить пакет. Microsoft.Extensions.Hosting.WindowsServices
2. Фреймворк мне нужен не просто .Net 8, а net8.0-windows и никак иначе!
3. В коде также надо специально указать, что я хочу именно виндовую службу: builder.Services.AddWindowsService.
4. Компилировать надо обязательно в релиз х64.

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

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

P.S. До чего же я рад, что Microsoft прикопали серверную разработку под винду и что я не имею ничего общего с десктоп разработкой!

#проекты
Чуть более десятка полезных запросов для Postgres собрал и оформил с примерами. Для одного поста в телегу - это слишком много (особенно с разметкой примеров вывода). Так что положил в виде gist на github:
🔸Текущие выполняемые запросы
🔸Запросы, выполняемые более 1 секунды
🔸Таблицы с % попадания в кэш при их использовании
🔸Размеры таблиц (включая индексы)
🔸Размеры индексов
🔸Размер текущей БД
🔸Размеры и наличие временных файлов
🔸Статистика по чтению индексов
🔸Статистика использования индексов
🔸Топ 5 самых активных таблиц
🔸Топ 5 самых активных индексов
🔸Никогда не использованные индексы
#postgres
Познакомился на практике с двумя шарповыми фреймворками для веб разработки: Razor Pages и Blazor. Оба позволяют писать фронтенд без js-a, на смеси c# и особого диалекта html.

Razor реализует паттерн MVC. Логика работы фреймворка примерно такая: поднимается сервер, который по согласованному множеству ссылок отдает в браузер html страницы по http.

Blazor несколько сложнее. Логика описывается на c#, после чего в браузер отдается нечто, висящее на веб сокете (SignalR) с бэком. Бэк отсылает обновления и реакции на действия юзеров, они отрисовываются. Такой черный магический ящик. Вообще, есть вариант Blazor-а, отдающий в браузер клиент на WebAssembly, но я не тыкал его пока.

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

#front
Тут против России внезапно ввёл санкции докер. По утру отвалилась сборка контейнеров, завязанных на DockerHub. Проектов на c# это не коснулось: базовые образы тянутся с сайта Microsoft.

Решений у проблемы несколько:
1. Использовать vpn на сервере для сборок.
2. Использовать свежезапущенный проект хуёкер: https://huecker.io/
3. Закешировать нужные для сборок базовые образы у себя в экосистеме и либо переписать докерфайлы, чтобы они тянули с ваших хранилищ, либо понадеятся на кеширование самого докера.

UPD. Я бы пока не стал пользоваться хуёкером, ибо все мы помним SDEK. А вот зеркалом Гугла (mirror.gcr.io)- вполне.
Некоторое время назад потыкал питоновские фреймворки на предмет быстрого создания веб апи. Мои требования:
1. Сваггер с описаниями методов и полей.
2. Типизированные модели, чтобы всякий мусор присылаемых извне отваливался на этапе десериализации.
3. Упаковка проекта в докер, желательно из коробки.

Этот набор требований - то что в c# даётся из коробки в шаблоне проекта.

Сначала я попробовал по старой памяти потыкать Flask. Читаю про сваггер. Можно подключить его десятком разных способов, в некоторых случаях мне предлагают прицепить yml описание методов.

Посмотрел в Django. Оказывается все не так плохо как несколько лет назад: туда завезли асинхронщину, не прошло и 10 лет. Сваггер описывается вроде нормально. Но тащить весь джанговский зверинец вместе с MVC для легковесной апишки мне запрещают религиозные убеждения. Плюс Django надо отдельно изучать, шарповый опыт не особо помогает понимать происходящее.

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

Все бы ничего, но возник вопрос: а питон - это точно про сделать что-то без боли и мучений?

#python
Кстати сегодня день рождения .NET Core (да, тогда он назывался так).
27 июня 2016го года - день релиза .NET Core 1.0 :)
Продолжил читать Рихтера, дошел до делегатов. Делегат - это тип, описывающий метод: входящие и выходящие параметры. Можно например сделать метод, принимающий на вход делегат и вызывающий его внутри. И таким образом по ситуации подменять вызываемый метод. В общем штука банальная, иметь такое мне захотелось ~на третий месяц программирования на c#.

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

Метод из цепочки также можно удалить вызвав -= метод.

#csharp
#Рихтер
#книги
Некоторое время назад я познакомился с отличным образцом импортозамещения: проектом для быстрой генерации отчётов - FastReports. Свой род они ведут из древних тёмных времен, когда Delphi был мейнстримным языком.

Идея отличная: нужен какой-то красивый отчёт? Аналитик рисует макет в редакторе, пишет sql запрос, получает красивую страничку с возможностью выгрузки в pdf.

А вот реализация немного подкачала, поделюсь некоторыми впечатлениями:

С MS SQL работа идёт из коробки. А чтобы подключиться к постгресу - надо подключить расширение. Для этого вы можете собрать нужную dll-ку воооот из этих исходников, которые доложили в ProgramFiles при установке. Исходники на c#. Что характерно, в руках у меня, шарписта, они что-то не билдятся. В итоге пришлось чуть-чуть подправить их. А так - FastReports - инструмент, который можно дать в руки аналитику, чтобы он просто шлёпал отчётики, да.

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

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

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

P.S. Я бы для репортинга лучше посадил джун+ фронтендера в пару к аналитику клепать отчетики на реакте.

#fastreports
2025/07/07 15:09:07
Back to Top
HTML Embed Code: