P.S. При публикации потерял картинку ко 2й части, оставлю тут.
Sphagnum. Часть 6. Техобзор. Репликация и отказоустойчивость в Kafka
#sphagnum@eshu_coding
Кафка по умолчанию сохраняет все сообщения, которые проходят через нее. У каждого сообщения есть свой offset - его порядковый номер. Соответственно, реплики в случае отставания просто просят у мастера "дай мне все сообщения больше моего оффесета". Если отставания нет - получают их в режиме реального времени. По умолчанию сообщение может быть отправлено клиенту только после того, как все реплики подтвердят его получение. Kafka старается поддерживать реплики в состоянии in-sync replicas (ISR), то есть когда состояние реплик идентично.
Выбор нового мастера в случае отказа предыдущего осуществляются инстансом Кафки, имеющим статус Controller-a. Если контроллер оказался мертв, оставшиеся в живых реплики пытаются на скорость занять его место, кто успел - тот и новый контроллер. Из группы реплик, находящихся в статусе ISR выбирается один лидер, через которого осуществляется дальнейшая работа.
Итого, из того, что мне пока хотелось бы взять для своего проекта:
1. Мне очень понравилась идея хранить историю сообщений и по ситуации отдавать ее с определенного offset-а.
2. Идея ISR тоже хороша.
#sphagnum_theory@eshu_coding
#kafka
#sphagnum@eshu_coding
Кафка по умолчанию сохраняет все сообщения, которые проходят через нее. У каждого сообщения есть свой offset - его порядковый номер. Соответственно, реплики в случае отставания просто просят у мастера "дай мне все сообщения больше моего оффесета". Если отставания нет - получают их в режиме реального времени. По умолчанию сообщение может быть отправлено клиенту только после того, как все реплики подтвердят его получение. Kafka старается поддерживать реплики в состоянии in-sync replicas (ISR), то есть когда состояние реплик идентично.
Выбор нового мастера в случае отказа предыдущего осуществляются инстансом Кафки, имеющим статус Controller-a. Если контроллер оказался мертв, оставшиеся в живых реплики пытаются на скорость занять его место, кто успел - тот и новый контроллер. Из группы реплик, находящихся в статусе ISR выбирается один лидер, через которого осуществляется дальнейшая работа.
Итого, из того, что мне пока хотелось бы взять для своего проекта:
1. Мне очень понравилась идея хранить историю сообщений и по ситуации отдавать ее с определенного offset-а.
2. Идея ISR тоже хороша.
#sphagnum_theory@eshu_coding
#kafka
Telegram
Эшу быдлокодит
Sphagnum. Часть 1. Начало.
#sphagnum@eshu_coding
Начинаю новый пет-проект: свой брокер сообщений. Обозвал я его пока Sphagnum, проект планируется в качестве чисто образовательного, под лицензией MIT. Что я хочу получить на выходе:
1. По основному функционалу…
#sphagnum@eshu_coding
Начинаю новый пет-проект: свой брокер сообщений. Обозвал я его пока Sphagnum, проект планируется в качестве чисто образовательного, под лицензией MIT. Что я хочу получить на выходе:
1. По основному функционалу…
Sphagnum. Часть 6. Техобзор. Репликация и отказоустойчивость в Tarantool
#sphagnum@eshu_coding
Тарантул изначально проектировался как решение, которое можно без боли (ха-ха) раскатать в бесконечное по размеру облако. Вообще, про взаимодействие между инстансами можно почитать вполне себе неплохую статью на Хабре. Если кратко, инстансы обмениваются друг с другом "слухами" о происходящих событиях по UDP (с помощью механизма SWIM) и формируюткартину мира текущее состояние кластера. В случае падения мастера, выборами занимаются специальные инстансы тарантула, имеющие роль failover coordinator. Текущее состояние кластера сохраняется или в etcd (распределенное хранилище ключ-значенин) или в специфическом инстансе тарантула.
И также неплохая статья про механизм репликации. Если коротко - между мастером и репликами распространяется журнал WAL мастера. При том, распространяется отдельными процессами, живущими рядом с основным тарантулом, по процессу на реплику. Репликация может осуществляться как асинхронно (транзакция считается выполненной до того, как все реплики подтвердят получение данных), так и синхронно. Для синхронной репликации используется алгоритм Raft.
Что мне очень понравилось в тарантуле - удобный ui для создания и управления кластером (входит в Tarantool Cartridge). В нем можно проставить репликам как дефолтные роли (failover coordinator, master, replica, router), так и пользовательские, включающие определенный набор "таблиц" и хранимок. При желании, этот же ui можно использовать для написания или правки хранимых процедур и распространения обновлений по кластеру. Все команды ui также могут быть продублированы в виде скриптов в командной строке (что я и делал).
Итого, из того, что мне пока хотелось бы взять для своего проекта:
1. UI + дублирующие консольные команды, позволяющие создать кластер без боли. И выбор ролей инстансов через UI - тоже огонь.
2. Идея обмена слухами о происходящем в кластере хороша.
#sphagnum_theory@eshu_coding
#tarantool
#sphagnum@eshu_coding
Тарантул изначально проектировался как решение, которое можно без боли (ха-ха) раскатать в бесконечное по размеру облако. Вообще, про взаимодействие между инстансами можно почитать вполне себе неплохую статью на Хабре. Если кратко, инстансы обмениваются друг с другом "слухами" о происходящих событиях по UDP (с помощью механизма SWIM) и формируют
И также неплохая статья про механизм репликации. Если коротко - между мастером и репликами распространяется журнал WAL мастера. При том, распространяется отдельными процессами, живущими рядом с основным тарантулом, по процессу на реплику. Репликация может осуществляться как асинхронно (транзакция считается выполненной до того, как все реплики подтвердят получение данных), так и синхронно. Для синхронной репликации используется алгоритм Raft.
Что мне очень понравилось в тарантуле - удобный ui для создания и управления кластером (входит в Tarantool Cartridge). В нем можно проставить репликам как дефолтные роли (failover coordinator, master, replica, router), так и пользовательские, включающие определенный набор "таблиц" и хранимок. При желании, этот же ui можно использовать для написания или правки хранимых процедур и распространения обновлений по кластеру. Все команды ui также могут быть продублированы в виде скриптов в командной строке (что я и делал).
Итого, из того, что мне пока хотелось бы взять для своего проекта:
1. UI + дублирующие консольные команды, позволяющие создать кластер без боли. И выбор ролей инстансов через UI - тоже огонь.
2. Идея обмена слухами о происходящем в кластере хороша.
#sphagnum_theory@eshu_coding
#tarantool
Хабр
Отказоустойчивая архитектура: почему Tarantool не падает?
Основная проблема в высоконагруженных приложениях — отказоустойчивость. Нагрузка с упавших узлов в кластере должна переключаться на живые. Это кажется несложной задачей, но на практике появляется...
👍1
Sphagnum. Часть 7. Техобзор. Репликация и отказоустойчивость в NATS
#sphagnum@eshu_coding
NATS - брокер сообщений, написанный на Go как альтернатива мейнстримным решениям - RabbitMQ и Apache Kafka. Отличительная особенность - он может подключаться в приложения, разрабатываемые на Go как dll-ка. Собственно, этот проект и вдохновил меня на разработку своего брокера сообщений. Изначально NATS был легковесным
Standalone решением, не предполагающим
кластеризацию и персистентное хранение данных. Но вскоре эти
механизмы также завезли,
породив по сути два NATS-а - классический и с наворотами. В чём-то это
похоже на развитие Tarantool.
NATS в кластерной версии, как и Tarantool, использует алгоритм Raft для выявления лидера. Кроме того, данные, попавшие в инстанс, отдаются только его непосредственным соседям. А соседи дальше их не передают. Так формируются Stream groups - группы инстансов внутри кластера с синхронизированным состоянием. Впрочем, как я понял, есть пути пустить данные дальше. Аналогично могут формироваться Consumer groups - группировки инстансов по подключенным клиентам-подписчикам. Как я понимаю (возможно ошибочно), таким образом может достигаться ограниченное горизонтальное масштабирование. В NATS данные могут сохраняться как на диск, так и в СУБД, например - постгрес.
Итого, из того, что мне пока хотелось бы взять для своего проекта:
1. Мне очень понравилась идея дополнительной сегментации вроде бы единого кластера.
2. Идея сохранения данных не на диск, а в СУБД выглядит очень интересно, по крайней мере на этапе разработки, чтобы отложить в сторону вопросы оптимальной укладки данных на жёсткий диск.
#sphagnum_theory@eshu_coding
#nats
#sphagnum@eshu_coding
NATS - брокер сообщений, написанный на Go как альтернатива мейнстримным решениям - RabbitMQ и Apache Kafka. Отличительная особенность - он может подключаться в приложения, разрабатываемые на Go как dll-ка. Собственно, этот проект и вдохновил меня на разработку своего брокера сообщений. Изначально NATS был легковесным
Standalone решением, не предполагающим
кластеризацию и персистентное хранение данных. Но вскоре эти
механизмы также завезли,
породив по сути два NATS-а - классический и с наворотами. В чём-то это
похоже на развитие Tarantool.
NATS в кластерной версии, как и Tarantool, использует алгоритм Raft для выявления лидера. Кроме того, данные, попавшие в инстанс, отдаются только его непосредственным соседям. А соседи дальше их не передают. Так формируются Stream groups - группы инстансов внутри кластера с синхронизированным состоянием. Впрочем, как я понял, есть пути пустить данные дальше. Аналогично могут формироваться Consumer groups - группировки инстансов по подключенным клиентам-подписчикам. Как я понимаю (возможно ошибочно), таким образом может достигаться ограниченное горизонтальное масштабирование. В NATS данные могут сохраняться как на диск, так и в СУБД, например - постгрес.
Итого, из того, что мне пока хотелось бы взять для своего проекта:
1. Мне очень понравилась идея дополнительной сегментации вроде бы единого кластера.
2. Идея сохранения данных не на диск, а в СУБД выглядит очень интересно, по крайней мере на этапе разработки, чтобы отложить в сторону вопросы оптимальной укладки данных на жёсткий диск.
#sphagnum_theory@eshu_coding
#nats
Вот и закончилась первая часть обзора. Я не ставил себе целью досконально описать каждый из продуктов, для моих целей достаточно общего понимания предметной области.
Следующим этапом постараюсь отыскать ссылки на методы, используемые для организации распределенных транзакций в известнейших СУБД и брокерах сообщения, а затем начну углубляться в каждый из них.
#sphagnum_theory@eshu_coding
Следующим этапом постараюсь отыскать ссылки на методы, используемые для организации распределенных транзакций в известнейших СУБД и брокерах сообщения, а затем начну углубляться в каждый из них.
#sphagnum_theory@eshu_coding
Telegram
Эшу быдлокодит
Sphagnum. Часть 3. Техобзор, начало.
#sphagnum@eshu_coding
Несмотря на нехватку времени продолжаю потихоньку заниматься новым проектом.
Прежде чем садиться писать код, нужно изучить некоторые моменты, чтобы потом не строить велосипеды из костылей. В науке…
#sphagnum@eshu_coding
Несмотря на нехватку времени продолжаю потихоньку заниматься новым проектом.
Прежде чем садиться писать код, нужно изучить некоторые моменты, чтобы потом не строить велосипеды из костылей. В науке…
Подведу итоги года.
В начале января 2023 я решил посмешить богов и опубликовал пост со своими планами на год, пойду по пунктам:
1. Я хотел познакомиться с современной фронтенд разработкой (React.js). Познакомился, осознал основные концепции, необходимые для разработки фронтенда на React-е. Теперь можно начинать что-то писать и набивать руку, но желания нет от слова совсем.
2. Я хотел заполнить пробел в знаниях и познакомиться на практике с ORM Entity Framework. Познакомился, шишек понабивал.
3. В постгрес углубиться не удалось, просто вспомнил забытое с 2021 года и не более того.
4. Я хотел читать умные книжки. Читал намного меньше чем хотелось, осилил только половину Рихтера.
5. Не делал вообще ничего в этом направлении:)
Но наверное главный итог года - что я таки дополз до лычки сеньора и сеньорских должностей и задач соответственно. Теперь движемся в сторону техлида/архитектора.
В начале января 2023 я решил посмешить богов и опубликовал пост со своими планами на год, пойду по пунктам:
1. Я хотел познакомиться с современной фронтенд разработкой (React.js). Познакомился, осознал основные концепции, необходимые для разработки фронтенда на React-е. Теперь можно начинать что-то писать и набивать руку, но желания нет от слова совсем.
2. Я хотел заполнить пробел в знаниях и познакомиться на практике с ORM Entity Framework. Познакомился, шишек понабивал.
3. В постгрес углубиться не удалось, просто вспомнил забытое с 2021 года и не более того.
4. Я хотел читать умные книжки. Читал намного меньше чем хотелось, осилил только половину Рихтера.
5. Не делал вообще ничего в этом направлении:)
Но наверное главный итог года - что я таки дополз до лычки сеньора и сеньорских должностей и задач соответственно. Теперь движемся в сторону техлида/архитектора.
Telegram
Эшу быдлокодит
Ну чтож, надо посмешить богов, озвучить свои планы.
Чего хочу я в этом году:
1. Немного обмазаться фронтенд разработкой, но без фанатизма. Пока думаю о связке React + Typescript.
2. Попробовать на практике стандартную шарповую ORM: Entity Framework.
3.…
Чего хочу я в этом году:
1. Немного обмазаться фронтенд разработкой, но без фанатизма. Пока думаю о связке React + Typescript.
2. Попробовать на практике стандартную шарповую ORM: Entity Framework.
3.…
👏7🔥2👍1
Анонсирую наверное ещё один проект, которым хочу заняться уже третий год. Это автоматизация настольной ролевой игры Trail of Cthulhu, дальше будет под тегом #cthulhu@eshu_coding. Про саму игру можно подробнее почитать на той же тесере. Правила мудрёны и путаны, потому систематизировать и описать их в виде кода - занятная задача.
Планирую чисто мобильное приложение + бэкенд, возможно - вариант без бэкенда, для взаимодействия между несколькими мобильными устройствами, изолированными от интернета. Приложение строго для домашнего использования, максимум - с друзьями, чтобы не париться на предмет авторских прав и прочего.
Приложение довольно простое. Основной элемент игры - лист сыщика (персонажа), таблица с ~100 меняющимися по разным законам параметрами. Для некоторых сыщиков - законы свои. Также нужно предусмотреть несколько действий, которые может совершить сыщик. И чатик/поле для записей, ну и сохранение истории происходящего.
В далёком светлом будущем ещё хотелось бы сделать поиск по правилам, но это уже рюшечки.
Я несколько раз подступался к разработке, но дальше размышлений и купленного домена так и не продвинулся.
#проекты
Планирую чисто мобильное приложение + бэкенд, возможно - вариант без бэкенда, для взаимодействия между несколькими мобильными устройствами, изолированными от интернета. Приложение строго для домашнего использования, максимум - с друзьями, чтобы не париться на предмет авторских прав и прочего.
Приложение довольно простое. Основной элемент игры - лист сыщика (персонажа), таблица с ~100 меняющимися по разным законам параметрами. Для некоторых сыщиков - законы свои. Также нужно предусмотреть несколько действий, которые может совершить сыщик. И чатик/поле для записей, ну и сохранение истории происходящего.
В далёком светлом будущем ещё хотелось бы сделать поиск по правилам, но это уже рюшечки.
Я несколько раз подступался к разработке, но дальше размышлений и купленного домена так и не продвинулся.
#проекты
👍4🤡1
Forwarded from .NET Разработчик
День 1804. #TipsAndTricks
10 Крутых Трюков в C#. Продолжение
1-2
3-4
5
6
7
8. Динамическая компиляция кода с Roslyn
Динамическая компиляция кода с помощью Roslyn позволяет компилировать и выполнять код C# во время выполнения. Это может быть полезно для сценариев, плагинов или ситуаций, когда код необходимо генерировать или изменять «на лету».
Вывод:
Как это работает и почему это полезно:
В примере выше метод ExecuteDynamicCodeAsync демонстрирует, как скомпилировать и выполнить фрагмент кода C# во время выполнения с помощью компилятора Roslyn. Метод Roslyn CSharpSyntaxTree.ParseText используется для анализа исходного кода в синтаксическое дерево, которое затем добавляется в новый объект CSharpCompilation. К объекту компиляции также добавляются необходимые ссылки на сборки: библиотеку CoreLib, System.Runtime и System.Console для работы класса Console. Заметьте, что в последних версиях .NET они находятся в разных файлах.
Метод Emit компилирует код в динамически подключаемую библиотеку (DLL) и записывает выходные данные в MemoryStream. Если компиляция прошла успешно, полученная сборка загружается в текущий домен приложения с помощью метода Assembly.Load. Затем класс Runner и его метод Run получаются через рефлексию, и этот метод вызывается, выполняя динамический код.
Этот метод позволяет создавать гибкие и расширяемые приложения, которые могут динамически компилировать и выполнять код C# во время выполнения. Однако будьте осторожны с последствиями для безопасности, поскольку выполнение произвольного кода может создать угрозу безопасности, если с ним не обращаться должным образом.
Продолжение следует…
Источник: https://maherz.medium.com/10-mind-blowing-c-hacks-95fa629cfcef
10 Крутых Трюков в C#. Продолжение
1-2
3-4
5
6
7
8. Динамическая компиляция кода с Roslyn
Динамическая компиляция кода с помощью Roslyn позволяет компилировать и выполнять код C# во время выполнения. Это может быть полезно для сценариев, плагинов или ситуаций, когда код необходимо генерировать или изменять «на лету».
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
async Task ExecuteDynamicCodeAsync(
string code)
{
string sourceCode = $@"
using System;
namespace DynamicCode;
public class Runner
{{
public static void Run()
{{
{code}
}}
}}
";
var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
var references = new List<MetadataReference>
{
MetadataReference.CreateFromFile(
Path.Combine(assemblyPath, "System.Private.CoreLib.dll")),
MetadataReference.CreateFromFile(
Path.Combine(assemblyPath, "System.Console.dll")),
MetadataReference.CreateFromFile(
Path.Combine(assemblyPath, "System.Runtime.dll"))
};
var compilation = CSharpCompilation.Create("DynamicCode")
.WithOptions(new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary))
.AddReferences(references)
.AddSyntaxTrees(syntaxTree);
using var ms = new MemoryStream();
var result = compilation.Emit(ms);
if (!result.Success)
{
Console.WriteLine("Компиляция не удалась");
return;
}
ms.Seek(0, SeekOrigin.Begin);
var assembly = Assembly.Load(ms.ToArray());
var type = assembly.GetType("DynamicCode.Runner");
var method = type.GetMethod("Run",
BindingFlags.Static | BindingFlags.Public);
method.Invoke(null, null);
}
// использование
await ExecuteDynamicCodeAsync(
"Console.WriteLine(\"Привет, динамический код!\");"
);
Вывод:
Привет, динамический код!
Как это работает и почему это полезно:
В примере выше метод ExecuteDynamicCodeAsync демонстрирует, как скомпилировать и выполнить фрагмент кода C# во время выполнения с помощью компилятора Roslyn. Метод Roslyn CSharpSyntaxTree.ParseText используется для анализа исходного кода в синтаксическое дерево, которое затем добавляется в новый объект CSharpCompilation. К объекту компиляции также добавляются необходимые ссылки на сборки: библиотеку CoreLib, System.Runtime и System.Console для работы класса Console. Заметьте, что в последних версиях .NET они находятся в разных файлах.
Метод Emit компилирует код в динамически подключаемую библиотеку (DLL) и записывает выходные данные в MemoryStream. Если компиляция прошла успешно, полученная сборка загружается в текущий домен приложения с помощью метода Assembly.Load. Затем класс Runner и его метод Run получаются через рефлексию, и этот метод вызывается, выполняя динамический код.
Этот метод позволяет создавать гибкие и расширяемые приложения, которые могут динамически компилировать и выполнять код C# во время выполнения. Однако будьте осторожны с последствиями для безопасности, поскольку выполнение произвольного кода может создать угрозу безопасности, если с ним не обращаться должным образом.
Продолжение следует…
Источник: https://maherz.medium.com/10-mind-blowing-c-hacks-95fa629cfcef
.NET Разработчик
День 1804. #TipsAndTricks 10 Крутых Трюков в C#. Продолжение 1-2 3-4 5 6 7 8. Динамическая компиляция кода с Roslyn Динамическая компиляция кода с помощью Roslyn позволяет компилировать и выполнять код C# во время выполнения. Это может быть полезно для сценариев…
Компилировать код из текстового исходника - это в общем-то наркомания годится только для демонстрации пути. В реальной жизни такое неприменимо по соображениям безопасности. Но есть более реальный кейс.
Предположим, у нас огромный монолит. Релизный цикл - мягко говоря небыстрый, кодовая и тестовая базы огромны.
И вот нам надо предлагать клиентам гибкие персональные условия и предложения, возможно - формировать недостающие на ходу.
Один из путей - написать много (более 100) кирпичиков разной сложности, из которых формируются предложения и отдать формирование финальных условий на откуп менеджерам, работающим с клиентами. Они просто двигают квадратики в UI и собирают пакет услуг. Нажимают кнопочку - монолит пополняется новым методом/классом. Конфигурация метода сохраняется в специально выделенную базу и на этапе деплоя монолита дособирается из нее.
А ещё интереснее подобный функционал выглядит в сочетании с инструментом для построения workflow-архитектуры, о котором я слышал на конференции dotnext осенью.
Предположим, у нас огромный монолит. Релизный цикл - мягко говоря небыстрый, кодовая и тестовая базы огромны.
И вот нам надо предлагать клиентам гибкие персональные условия и предложения, возможно - формировать недостающие на ходу.
Один из путей - написать много (более 100) кирпичиков разной сложности, из которых формируются предложения и отдать формирование финальных условий на откуп менеджерам, работающим с клиентами. Они просто двигают квадратики в UI и собирают пакет услуг. Нажимают кнопочку - монолит пополняется новым методом/классом. Конфигурация метода сохраняется в специально выделенную базу и на этапе деплоя монолита дособирается из нее.
А ещё интереснее подобный функционал выглядит в сочетании с инструментом для построения workflow-архитектуры, о котором я слышал на конференции dotnext осенью.
🤔3
Попробую посмешить богов и в этом году. Планы на 2024 год.
1. Читать умные книжки:
- Рихтер
- Внедрение зависимостей на платформе .Net (Симан, ван Дерсен)
- Чистая архитектура (Роберт Мартин)
- Высоконагруженные приложения (Мартин Клеппман)
2. Осознать до конца некоторые архитектурные загибы:
- Аспекто-ориентированное программирование
- Акторы
- Углубиться в DDD
3. На практике освоить магию Source Generators - на этапе компиляции c# проекта, компилятор по заранее заданным правилам анализирует созданное им, на основании анализа генерирует некоторое количество нового c# кода, компилирует снова вместе с генеренным кодом и так сколько настроишь раз.
4. Таки потыкать алгоритмы, задачки на литкоде.
5. Добраться до кода с пет проектом #sphagnum.
6. Добраться до кода с пет проектом #cthulhu
7. Есть желание переписать и перезапустить #палантир@eshu_coding.
1. Читать умные книжки:
- Рихтер
- Внедрение зависимостей на платформе .Net (Симан, ван Дерсен)
- Чистая архитектура (Роберт Мартин)
- Высоконагруженные приложения (Мартин Клеппман)
2. Осознать до конца некоторые архитектурные загибы:
- Аспекто-ориентированное программирование
- Акторы
- Углубиться в DDD
3. На практике освоить магию Source Generators - на этапе компиляции c# проекта, компилятор по заранее заданным правилам анализирует созданное им, на основании анализа генерирует некоторое количество нового c# кода, компилирует снова вместе с генеренным кодом и так сколько настроишь раз.
4. Таки потыкать алгоритмы, задачки на литкоде.
5. Добраться до кода с пет проектом #sphagnum.
6. Добраться до кода с пет проектом #cthulhu
7. Есть желание переписать и перезапустить #палантир@eshu_coding.
tesera.ru
Ктулху / Trail of Cthulhu | Tesera
Trail of Cthulhu — настольная ролевая игра, приключения в мире Лавкрафтовского ужаса, разыгрываемые по правилам «СЫЩИК» (GUMSHOE).
👍3🔥1
Как обычно ставят нугет пакеты? Зашёл в менеджер, выбрал версию, поставил, побежал дальше писать код.
Предположим, наша инфраструктура растет, у нас появляются собственные нугет пакеты, мы их активно используем, чтобы не копипастить код и не впадать в микросервисное безумие.
Мы продолжаем расти и развиваться. Часть наших пакетов начинает ссылаться на другие наши пакеты. Которые ссылаются на другие наши пакеты. Которые ссылаются на другие наши пакеты.Ой, рекурсия. На самом деле, циклическую зависимость создать никто не даст, но деревья зависимостей могут быть очень развесистыми.
И в какой-то момент ссылки начинают пересекаться. И если мы работаем обычным образом - как описано в начале поста - рано или поздно два установленных пакета начнут ссылаться на разные версии одного и того же пакета. И тут мы попадаем в ад конфликтующих зависимостей, из которого выход только один: в окно. Впрочем, в ад можно попасть даже если два проекта в решении ссылаются на разные версии одного и того же пакета, без всяких страшных древ зависимостей.
Лучше подобные проблемы не решать, а предотвращать, не допуская даже саму возможность появления.
Во-первых, продумать структуру решения. В идеале - нарисовать схему взаимных зависимостей проектов и установленных в них пакетов. И идеале, один пакет в решении должен устанавливаться один раз. Если мы ставим пакет 1 и пакет 2, зависящий от пакета 1, прямую установку пакета 1 мы тоже можем удалить.
Во-вторых, можно указать не конкретную версию пакета, а диапазон, например [1.0.0,3.0.0). В этот интервал попадут все пакеты, имеющие версию 1 или 2. Если у другого пакета будет [1.2.0,2.5.0) - при сборке будет подобрана версия, удовлетворяющая обоим интервалам условий.
В-третьих, версии пакетов можно выносить в константы и подтягивать из .props файлов. Предположим, часть функционала у нас вынесена в пакеты, имеющие в названии "Common", например Common.Math, Common.StringParsing, Common.HttpHelper. Мы можем ввести внутреннее правило - двигать версии этих пакетов только вместе (как на уровне регламента, так и в CI/CD). В .props мы можем определить параметр ${CommonPackageVersion}, после чего в проекте согласованно выставлять все версии Common пакетов через .props файл, указывая в .csproj файлах вместо привычных численных версий пакетов значение ${CommonPackageVersion}
P.S. больше информации по нугет пакетам можно посмотреть в официальной документации.
#csharp
Предположим, наша инфраструктура растет, у нас появляются собственные нугет пакеты, мы их активно используем, чтобы не копипастить код и не впадать в микросервисное безумие.
Мы продолжаем расти и развиваться. Часть наших пакетов начинает ссылаться на другие наши пакеты. Которые ссылаются на другие наши пакеты. Которые ссылаются на другие наши пакеты.
И в какой-то момент ссылки начинают пересекаться. И если мы работаем обычным образом - как описано в начале поста - рано или поздно два установленных пакета начнут ссылаться на разные версии одного и того же пакета. И тут мы попадаем в ад конфликтующих зависимостей, из которого выход только один: в окно. Впрочем, в ад можно попасть даже если два проекта в решении ссылаются на разные версии одного и того же пакета, без всяких страшных древ зависимостей.
Лучше подобные проблемы не решать, а предотвращать, не допуская даже саму возможность появления.
Во-первых, продумать структуру решения. В идеале - нарисовать схему взаимных зависимостей проектов и установленных в них пакетов. И идеале, один пакет в решении должен устанавливаться один раз. Если мы ставим пакет 1 и пакет 2, зависящий от пакета 1, прямую установку пакета 1 мы тоже можем удалить.
Во-вторых, можно указать не конкретную версию пакета, а диапазон, например [1.0.0,3.0.0). В этот интервал попадут все пакеты, имеющие версию 1 или 2. Если у другого пакета будет [1.2.0,2.5.0) - при сборке будет подобрана версия, удовлетворяющая обоим интервалам условий.
В-третьих, версии пакетов можно выносить в константы и подтягивать из .props файлов. Предположим, часть функционала у нас вынесена в пакеты, имеющие в названии "Common", например Common.Math, Common.StringParsing, Common.HttpHelper. Мы можем ввести внутреннее правило - двигать версии этих пакетов только вместе (как на уровне регламента, так и в CI/CD). В .props мы можем определить параметр ${CommonPackageVersion}, после чего в проекте согласованно выставлять все версии Common пакетов через .props файл, указывая в .csproj файлах вместо привычных численных версий пакетов значение ${CommonPackageVersion}
P.S. больше информации по нугет пакетам можно посмотреть в официальной документации.
#csharp
👍4
Познакомился с занятным инструментом для рисования графиков в документации к коду не выходя из гита. Самый простой способ что-то написать про проект - вписать это в Readme в формате markdown. У этого формата есть расширение для формирования иллюстраций - Mermaid.
Делаешь специальный блок в документе и пошёл описывать контент иллюстрации на чем-то напоминающем декларативный язык программирования. Задал основные объекты, ниже описал связи - получил симпатичную иллюстрацию. Расстановкой элементов графика занимается автоматика, от пишущего документацию требуется только накидать контент.
Очень удобно сделать отдельную ветку для документации прямо в интерфейсе гитлаба/гитхаба и там же править документ, переключаясь между вкладками Edit и Preview. Первые несколько подходов у меня текла кровь из глаз по попытке разобраться в коде, формирующем иллюстрации. Но когда отодвигать погружение стало некуда - на первичное освоение инструмента ушло около 30 минут.
Раньше я делал схемы и иллюстрации к проектам какзавещали деды учили в универе: открываем inkscape и рисуем векторную картинку. С новым для меня инструментом все стало в разы быстрее. А в дополнение мы получаем все плюшки гита: версионирование и лог всех изменений с возможностью быстрого отката на старые версии.
В качестве примера попробовал набросать иллюстрацию схемы сервисов абстрактной системы, включающей две базы данных, фронтенд, апишку, брокер сообщений, телеграм бота и сервис - обработчик данных. На все ушло минут 5, получилась вполне пристойная картинка. Ниже приведен "код", формирующий иллюстрацию:
Видов возможных диаграмм масса, можно подобрать себе тип под любую задачу, связанную с документированием процесса разработки.
P.S. Из забавного - в гите не предусмотрели возможности скопировать диаграмму отдельно как картинку.
Делаешь специальный блок в документе и пошёл описывать контент иллюстрации на чем-то напоминающем декларативный язык программирования. Задал основные объекты, ниже описал связи - получил симпатичную иллюстрацию. Расстановкой элементов графика занимается автоматика, от пишущего документацию требуется только накидать контент.
Очень удобно сделать отдельную ветку для документации прямо в интерфейсе гитлаба/гитхаба и там же править документ, переключаясь между вкладками Edit и Preview. Первые несколько подходов у меня текла кровь из глаз по попытке разобраться в коде, формирующем иллюстрации. Но когда отодвигать погружение стало некуда - на первичное освоение инструмента ушло около 30 минут.
Раньше я делал схемы и иллюстрации к проектам как
В качестве примера попробовал набросать иллюстрацию схемы сервисов абстрактной системы, включающей две базы данных, фронтенд, апишку, брокер сообщений, телеграм бота и сервис - обработчик данных. На все ушло минут 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. Из забавного - в гите не предусмотрели возможности скопировать диаграмму отдельно как картинку.
👍5
Эшу быдлокодит
Познакомился с занятным инструментом для рисования графиков в документации к коду не выходя из гита. Самый простой способ что-то написать про проект - вписать это в Readme в формате markdown. У этого формата есть расширение для формирования иллюстраций - Mermaid.…
Для тех, кому лениво идти на гитхаб - скрин иллюстрации, получившейся из "кода" в посте выше.
🔥3👍2😱1
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) При асинхронной - наименее проблемный из имеющих последнюю версию данных.
Конфликты, когда все параметры кандидатов одинаковы решаются жребием:)
Со временем планирую добавить горизонтальную масштабируемость, но пока по ней есть только сырые идеи.
#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) При асинхронной - наименее проблемный из имеющих последнюю версию данных.
Конфликты, когда все параметры кандидатов одинаковы решаются жребием:)
Со временем планирую добавить горизонтальную масштабируемость, но пока по ней есть только сырые идеи.
Telegram
Эшу быдлокодит
Sphagnum. Часть 1. Начало.
#sphagnum@eshu_coding
Начинаю новый пет-проект: свой брокер сообщений. Обозвал я его пока Sphagnum, проект планируется в качестве чисто образовательного, под лицензией MIT. Что я хочу получить на выходе:
1. По основному функционалу…
#sphagnum@eshu_coding
Начинаю новый пет-проект: свой брокер сообщений. Обозвал я его пока Sphagnum, проект планируется в качестве чисто образовательного, под лицензией MIT. Что я хочу получить на выходе:
1. По основному функционалу…
👍4🤔2👏1
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
Заранее всех очень сильно благодарю!
У моей семьи хотят забрать имущество, наш семейный дом, чтобы оплатить долги спившегося отца-банкрота. Он даже вступил в сговор с финансовым управляющим ради этого.
Я прошу прочитать и максимально распространить статью. У нас осталось не так много времени до апелляционной инстанции, поэтому нужно привлечь общественный резонанс. Решение суда абсолютно несправедливое, в Год семьи и перед выборами отжимать у многодетной семьи дом ради чужих долгов.
Пожалуйста, если не вас затруднит:
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
Заранее всех очень сильно благодарю!
vc.ru
Мою семью лишают имущества в Год семьи, чтобы оплатить чужие долги — Andrey Varfolomeev на vc.ru
Бог свидетель, я совершенно не горел желанием выносить всю нашу семейную историю наружу, но ситуация не оставляет никакого выбора. Это первая часть, серии статей, в которых я расскажу, как удачно перед выборами и в начале объявленного Президентом же Года…
👍4👎1
Вышло очень хорошее описание потокобезопасных коллекций в c#.
Респект автору за то, что совместил в одном месте и базовую базу и некоторые нюансы по работе каждого из типов потокобезопасных коллекций, что делает статью оптимальным вариантом для знакомства с темой.
#csharp
Респект автору за то, что совместил в одном месте и базовую базу и некоторые нюансы по работе каждого из типов потокобезопасных коллекций, что делает статью оптимальным вариантом для знакомства с темой.
#csharp
Telegram
StepOne
Встречайте System.Collections.Concurrent !
Настал день публикации моей самой длинной статьи на Хабре...
Количество сил, потраченных на подготовку материала однозначно заслуживает вашего плюса ➕
Настал день публикации моей самой длинной статьи на Хабре...
Количество сил, потраченных на подготовку материала однозначно заслуживает вашего плюса ➕
👍1
Познал дзен написания автотестов в c#. Тесты я пишу уже довольно давно и помногу, но во основном функциональные/интеграционные, закрывающие функционал проекта в целом. При этом зависел я обычно только от объектов инфраструктуры: баз данных, брокеров сообщений и т.д. Модульные тесты тоже писал, но только на места с неочевидной сложной логикой, которая не помещается в голове.
Перенесемся в мир кровавого энтерпрайза. Представим ситуацию, когда наш сервис ходит по сети более чем в 10 других микросервисов. Куда ходят эти 10 микросервисов чтобы собрать информацию - представить страшно.
Поднимать все это добро каждый раз, когда приспичит проверить бизнес логику - не очень удобно даже в светлую эпоху контейнеризации. Тут на помощь нам приходят моки: обносим источник данных интерфейсом, а дальше в тестах в тестируемый класс с бизнес логикой подсовываем фейковую реализацию интерфейса.
До недавнего времени я пилил эту реализацию сам, но тут проникся двумя инструментами - NSubstitute и Autofixture. Первый позволяет создавать фейковые реализации, второй - инициализировать инстансы классов для возвратов с заполненными полями.
У NSubstitute понравилась возможность легко задавать конкретные кейсы из пар запрос - ответ, очень удобно и никакой логики внутри фейка самому писать (и потом поддерживать) не надо.
Autofixture мне не казалось чем-то нужным, до тех пор, пока мне не пришлось тестировать проброс информации из глубинных слоев наверх, с возвращаемой моделью (в сумме с вложенными классами) в пару тысяч строк. Говоришь: мне нужен объект, поля id, name, userid должны иметь заданные значения. Остальные - заполнятся по усмотрению библиотеки чем-то не-дефолтным. Раз - и объект для теста готов, без бесконечной лапши с инициализацией полей руками.
#csharp
#tests
Перенесемся в мир кровавого энтерпрайза. Представим ситуацию, когда наш сервис ходит по сети более чем в 10 других микросервисов. Куда ходят эти 10 микросервисов чтобы собрать информацию - представить страшно.
Поднимать все это добро каждый раз, когда приспичит проверить бизнес логику - не очень удобно даже в светлую эпоху контейнеризации. Тут на помощь нам приходят моки: обносим источник данных интерфейсом, а дальше в тестах в тестируемый класс с бизнес логикой подсовываем фейковую реализацию интерфейса.
До недавнего времени я пилил эту реализацию сам, но тут проникся двумя инструментами - NSubstitute и Autofixture. Первый позволяет создавать фейковые реализации, второй - инициализировать инстансы классов для возвратов с заполненными полями.
У NSubstitute понравилась возможность легко задавать конкретные кейсы из пар запрос - ответ, очень удобно и никакой логики внутри фейка самому писать (и потом поддерживать) не надо.
Autofixture мне не казалось чем-то нужным, до тех пор, пока мне не пришлось тестировать проброс информации из глубинных слоев наверх, с возвращаемой моделью (в сумме с вложенными классами) в пару тысяч строк. Говоришь: мне нужен объект, поля id, name, userid должны иметь заданные значения. Остальные - заполнятся по усмотрению библиотеки чем-то не-дефолтным. Раз - и объект для теста готов, без бесконечной лапши с инициализацией полей руками.
#csharp
#tests
Sphagnum. Часть 9. Доска задач и репозиторий.
#sphagnum@eshu_coding
При работе над проектом у меня возникают довольно большие паузы, иногда по нескольку недель. В итоге, когда возвращаешься к проекту, зачастую тратишь несколько часов на то, чтобы вспомнить, а что ты делал раньше и на чем вообще остановился.
Так возникла идея сделать себе доску и начинать весело двигать таски. Сначала я посмотрел на Asana, на одном из мест работы была она и в целом оставила приятные впечатления. В бесплатной версии мне не хватило интеграции с гитом, чтобы без проблем линковать коммиты к задачам.
Затем я подумал о Гитлабе. Весь нужный функционал есть, но вспомнил, сколько мороки с администрированием и настройкой и расхотел.
Зашёл на гитхаб - ux не очень. Быстро (в течение 2 минут) сделать минималистичный канбан в проекте не удалось.
Тогда я решил причаститься Gitea. Доска конкретного репозитория создалась за минуту, коммиты прилинковались, чек листы в задачах удобные. Зеркалирование на гитхаб настроилось мгновенно.
В целом, для работы в одного разработчика (или в маленькой команде) - отличное минималистичное решение, не перегруженное рюшечками, с интерфейсом, интуитивно понятным засыпающему разработчику.
#gitea
#cicd
#devops
#sphagnum@eshu_coding
При работе над проектом у меня возникают довольно большие паузы, иногда по нескольку недель. В итоге, когда возвращаешься к проекту, зачастую тратишь несколько часов на то, чтобы вспомнить, а что ты делал раньше и на чем вообще остановился.
Так возникла идея сделать себе доску и начинать весело двигать таски. Сначала я посмотрел на Asana, на одном из мест работы была она и в целом оставила приятные впечатления. В бесплатной версии мне не хватило интеграции с гитом, чтобы без проблем линковать коммиты к задачам.
Затем я подумал о Гитлабе. Весь нужный функционал есть, но вспомнил, сколько мороки с администрированием и настройкой и расхотел.
Зашёл на гитхаб - ux не очень. Быстро (в течение 2 минут) сделать минималистичный канбан в проекте не удалось.
Тогда я решил причаститься Gitea. Доска конкретного репозитория создалась за минуту, коммиты прилинковались, чек листы в задачах удобные. Зеркалирование на гитхаб настроилось мгновенно.
В целом, для работы в одного разработчика (или в маленькой команде) - отличное минималистичное решение, не перегруженное рюшечками, с интерфейсом, интуитивно понятным засыпающему разработчику.
#gitea
#cicd
#devops
Telegram
Эшу быдлокодит
Sphagnum. Часть 1. Начало.
#sphagnum@eshu_coding
Начинаю новый пет-проект: свой брокер сообщений. Обозвал я его пока Sphagnum, проект планируется в качестве чисто образовательного, под лицензией MIT. Что я хочу получить на выходе:
1. По основному функционалу…
#sphagnum@eshu_coding
Начинаю новый пет-проект: свой брокер сообщений. Обозвал я его пока Sphagnum, проект планируется в качестве чисто образовательного, под лицензией MIT. Что я хочу получить на выходе:
1. По основному функционалу…
👍9👏1
Освоил девопсячий минимум на базе Gitea. В целом - тот же gitlab, но без понтов и ощутимо проще.
Поставил раннер на сервер (скачав бинарник с официального сайта, в apt не завезли), зарегистрировал его. Вариант с установкой раннера в докере мне прям не понравился: требуется задать кучу переменных окружения, а чтобы понять зачем они все - надо включать мозг и читать документацию, чего не хочется.
Вставляем кусок yml скрипта из примера в папку для ci cd скриптов - управление командной строкой работает. Если гитлаб раннер может выполняться миллионом разных способов: и в докере, и в командной строке самой машины и ещё хрен знает как, тот у act_runner-а - раннера gitea - вариант один - в докер контейнере с node.js.
Хранилище докер образов (ипрочего мусора прочих артефактов, типа нугет пакетов) работает из коробки. Единственное, чтобы образы прикрепились к репозиторию, а не лежали в общей куче, надо вручную линкануть их через ui. Наверняка можно и через командную строку. Настроек автоочищения хранилища я не нашел.
В общем, отличное решение для микрокоманд. Но человек на 5 и более, работающих над одним проектом я бы уже ставил гитлаб.
#gitea
#devops
Поставил раннер на сервер (скачав бинарник с официального сайта, в apt не завезли), зарегистрировал его. Вариант с установкой раннера в докере мне прям не понравился: требуется задать кучу переменных окружения, а чтобы понять зачем они все - надо включать мозг и читать документацию, чего не хочется.
Вставляем кусок yml скрипта из примера в папку для ci cd скриптов - управление командной строкой работает. Если гитлаб раннер может выполняться миллионом разных способов: и в докере, и в командной строке самой машины и ещё хрен знает как, тот у act_runner-а - раннера gitea - вариант один - в докер контейнере с node.js.
Хранилище докер образов (и
В общем, отличное решение для микрокоманд. Но человек на 5 и более, работающих над одним проектом я бы уже ставил гитлаб.
#gitea
#devops
👍6🤮1
Продолжая тему модульных тестов в c#. Вляпался в занятную ситуацию с Autofixture. Строки и числа Autofixture заполняет случайными значениями, меняющимися от запуска тестов к запуску. А вот тот момент, что значения булевых полей меняются по другим законам я как-то упустил.
Удаляю я неиспользуемое поле в одном из классов, экземпляры которых я создаю с помощью Autofixture - и тут у меня перестает проходить несколько тестов, при том покрывающих вообще случайные места в проекте. А переименование поля (неиспользуемого) такого эффекта не оказывает.
Первое на что я подумал - что-то где-то закешировалось у меня на компе и тесты заглючили, так иногда бывает. Следующий час прошел в попытках провести экзорцизм над проектом. Не помогло, зато я выяснил что проблема воспроизводится и в пайплайне CI/CD на серверах. Приплыли.
В итоге, оказалось, что генерируемые с помощью Autofixture значения булевых полей не меняются от запуска к запуску тестов, но являются функцией от набора полей в классе. Убрали или добавили поле - значения поехали.
А ошибки полезли из-за того, что я их допустил при написании тестов. Сочетание сгенерированных булевых флагов делало их незаметными, но минус на минус перестал давать плюс и тайное стало явным.
#csharp
#tests
Удаляю я неиспользуемое поле в одном из классов, экземпляры которых я создаю с помощью Autofixture - и тут у меня перестает проходить несколько тестов, при том покрывающих вообще случайные места в проекте. А переименование поля (неиспользуемого) такого эффекта не оказывает.
Первое на что я подумал - что-то где-то закешировалось у меня на компе и тесты заглючили, так иногда бывает. Следующий час прошел в попытках провести экзорцизм над проектом. Не помогло, зато я выяснил что проблема воспроизводится и в пайплайне CI/CD на серверах. Приплыли.
В итоге, оказалось, что генерируемые с помощью Autofixture значения булевых полей не меняются от запуска к запуску тестов, но являются функцией от набора полей в классе. Убрали или добавили поле - значения поехали.
А ошибки полезли из-за того, что я их допустил при написании тестов. Сочетание сгенерированных булевых флагов делало их незаметными, но минус на минус перестал давать плюс и тайное стало явным.
#csharp
#tests
🔥3