Обновить
0
0

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

Отправить сообщение

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

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

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

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

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


P.S. Характеристики системы стоило бы добавить в саму статью. А то high load у каждого свой, кому-то и тысяча уже high.

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


Мысли вслух

Microsoft.Data.SqlClient параметр типа Structured (TVP) принимает либо DataTable, либо IEnumerable


Либо я что-то путаю, либо внутри оно все-таки работает. Некоторое время назад, как раз, реализовывал то, о чём писал выше (+ npgsql плагин для обработки DataTable, DbDataReader, логика представления композитных типов точно такая же).

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

Получается обертка, которая реализует DbDataReader, внутри держим IEnumerable<TRow>, внутри вызова Read вызывается MoveNext для нашей коллекции и все работает отлично (и по ходу дела драйвер дергает методы вроде GetDataTypeName/GetChar/GetString/etc в которых мы отдаем метаданные/данные нашей коллекции).

С Microsoft.Data.SqlClient версии 6.0.2 точно работает.

Это главная боль. Чтобы передать список объектов в процедуру, в Dapper нужно либо создавать DataTable (что дико аллоцирует память и медленно), либо писать вручную кастомные классы‑наследники IEnumerable<SqlDataRecord>. Это тонна бойлерплейта.


npgsql драйвер не поддерживает DataTable, т.е с PostgreSQL не заведется.

Вместо SqlDataRecord можно использовать реализовать DbDataReader, который будет итерировать по свойствам-колонкам и отдавать данные. Поддерживается ADO из коробки, кроме того, нет надобности тянуть Microsoft.SqlServer.*специфичные пространства имен.

Что касается аллокации и скорости, то тут можно пулинг использовать, постоянно пересоздавать DataTable необязательно (но не уверен на счет DataRow, вероятно их потребуется пересоздавать, но экономия все-таки будет). Метаданные (информация о колонках) так или иначе статичная, ее можно сохранить на уровне класса и DataTable (если пулить).

И не факт, что кода будет больше при таких модификациях (но скорость, конечно, надо замерять), но точно проще чем код для Source Generator

Хотя эти вопросы больше о сне, чем о QPS. С другой стороны, одно может привести к другому.

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

Так или иначе, это не спасёт от необходимости внести упомянутые 30–40 обновлений.

--


Помимо структуры, которая будет нужна приложению, будут и вещи, о которых оно вряд ли должно знать — условные пользователи, роли, файловые группы и т.д. Т.е БД управляют не как целостной сущностью, а размазывают ее по разным местам. Какой вариант централизации предполагается?

Даже если откинуть вопрос структуры, получается, что всё описание переносится из SQL-проекта (будь то SSDT или что-то другое) в проект с приложением/контекстом на C#. То есть вместо прямого DDL пишется C# со всеми вытекающими, что вряд ли будет короче.

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

Для маленьких систем ещё понимаю, но когда тебе нужно при добавлении колонки в таблицу, обновить 30-40 запросов вручную...

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


А вот без ORM нужно следить за актуальностью запрашиваемых полей

При использовании ORM не нужно обновлять контекст с описанием используемых таблиц? Все подхватится и добавится автоматически?

Фактически структура БД будет дублироваться: сначала условный DDL, а затем обновить контекст, аннотации и т.п.

А если контекст находится в отдельном репозитории или поставляется в виде отдельного пакета..

--

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

Для маленьких систем ещё понимаю

Что такое маленькая система?


--

Не знаю, какой инструмент считается наиболее популярным и гибким для работы с БД проектами под PostgreSQL, но под SQL Server есть SSDT, который позволяет работать в привычной для разработчиков манере (как с точки зрения разработки, так и с точки зрения CI/CD). В сочетании с хранимыми процедурами это просто сказка.

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

Решение должно быть универсальным и легко адаптируемым к разным средам

В данном случае оно не является универсальным, т.к предполагает наличие K8S.

Почему бы не запускать создание резервной копии через CI систему? Она не зависит от системы оркестрации и удовлетворяет остальным требованиям (изоляция, журналирование, мониторинг).

---

Не описан обратный процесс, т.е импорт резервная копии в RabbitMQ.

Если в кластере был потерян кворум, то это приведет к перманентной недоступности очередей типа Quorum, их потребуется пересоздать. Импорт не приводит к пересозданию объектов.

---

Если исходить исходить из того, что объекты в рамках RabbitMQ (exchange, queue, vhost, policy) статичные, то их создание через Terrafrom (состояние автоматически выгружается в бакет) + CI (журналирование, мониторинг) будет неплохим решением. За сохранность временных объектов (полагаю к таким можно отнести только очереди) отвечало бы приложение (по сути их потеря не должна быть критичной).

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность