Я просто указываю на тот факт, что они существуют, могут быть написаны не нами и не быть нам подконтрольными, т.е. существовать внутри nuget-пакета, например
В таком случае, это плохие пакеты, которые плохо спроектировали. Подобный аргумент можно и раздуть дальше — например, можно сказать, что, могут существовать такие пакеты, которые складывают статичные данные вообще в файл рядом с собой. Или еще куда. Что вы будете с ними делать, вмето пересоздания процесса перезапускать весь контейнер? Или всё же признаете, что это не проблема stateless хоста?
Мне кажется, вы как-то не так понимаете stateless/serverless. Из ваших претензий я почерпываю следующее:
Вы хотите, чтобы все статические классы магически обнулились. Но, надеюсь, вы понимаете, что магии не бывает, плюс (также надеюсь) вы знаете как работает .NET, и следовательно понимаете, что для этого обнуления потребуется пересоздать AppDomain (если уж не перезапускать весь процесс).
Вы также хотите, чтобы стартап "stateless" происходил максимально быстро и негодуете на медленную скорость подъёма приложения.
Но я не вижу, как именно вы подразумеваете, как это должно произойти. Возможно, через множество подготовленных одноразовых аппдоменов? Но ведь это же ужасно расточительно, тратить 100+мс процессора, чтобы выполнить один очень быстрый и не требовательный ресурс.
Еще одно противоречение вижу в ваших словах: вы противитесь не использованию стататичных классов, но топите за "stateless". Закономерный вопрос - нафига вам статичные классы, если, по вашей логике, в "stateless" вы ожидаете, что они будут постоянно обнуляться (что довольно дорого со стороны хоста)? У вас есть ваш хендлер-метод, есть весь контекст запроса, зачем вам статика?
Понимаете к чему я, или начнёте спрашивать, мол, ну а нестатичная переменная типа тоже почему не обнулялась?
Боюсь вас снова разочаровать, но вы неправильно протестировали. Моё решение не модифицирует магически поведение статичных классов. И не предполагает, что вы будете их использовать (так же, как бы вы не использовали их в обычной современной архитектуре любого приложения).
На мой взгляд, добавление такой абстракции и регистрация сервисов в serverless-приложениях делает их слишком тяжеловесными. И это мы ещё не зарегистрировали и не использовали ни одного сервиса, просто добавили для них обёртку.
Если вам не нужны сервисы, то вы их просто не регистрируйте. Но если (в контексте вашеих задач) они вам нужны, то вам в любом случае от них никуда не деться, с учетом того, что выше приложение постоянно выключают. Т.е. этот аргумент не играет ни в чью пользу.
когда вызовы происходят настолько часто, что подготовленный экземпляр существует всегда. Но в таком случае разработчик скорее всего захочет максимально оптимизировать время работы функции и будет наоборот отказываться от любых дополнительных абстракций.
Не понял. Если у вас долгоживущее приложение (из-за частых запросов), то регистрация сервисов (=стартап) как раз будет происходить лишь единожды.
Учитывая ваш текст из статьи, описываемый вами .NET хост просто подключает вашу библиотеку к себе в аппдомен и держит его там, дёргая ваши методы через рефлексию (или кодген). Благодаря этому наблюдению у меня сложилась картина, как можно это использовать без какой-либо боли, описанной вами в статье (но я мог что-то пропустить, так что жду обратной связи)
App.Run можно вызывать из любых потоков, в т.ч. из нескольких одновременно.
В BuildContainer инициализируете ваш DI, этот код будет запущен лишь один раз на весь хостовый процесс/аппдомен.
При любом вызове вы получаете ссылку на IServiceProvider, который находится в скоупе, который будет успешно закрыт после выполнения вышего делегата.
Как использовать: рисуете свой хендлер, внутри оборачиваете свой бизнес-код в делегат:
public class Handler { public string FunctionHandler(int arg) { return App.Run(provider => { // Здесь бизнес-код, все сервисы доступны через provider. return $"Hello world_{arg}"; }); } }
Уважаемый автор, нижайшепрошу прощения, но мне кажется, что вы проиграли пошли не туда ещё на этапе "Подготовка приложения".
Дело в том, что вам стоило задуматься и (вполне закономерно) осознать, что встреченная вами ситуация не так проблематична, как кажется на первый взгляд.
Видите ли, ее можно решить написав небольшую обёртку с DI (мы же хотим красиво), поставив лок против race condition, и все красиво запаковать в минимальное количество абстракций.
В таком виде бизнес-код можно будет писать хоть прямо в этих самых "хендлерах", обернув их, разве что, в делегат.
Да вроде бы именно так вы и сказали: из вашего личного опыта вы считаете наличие некоего функционала минусом. "Наличие" может быть применимо только к пакету, в котором этот функционал находится.
NeoNN описал просто набор дополнительного сахара, но там есть и вещи, которые невозможны в принципе в стандартном DI, их туда просто еще не завезли.
Например, декораторы, или упомянутые интерцепторы.
Еще там есть очень полезная регистрация по ключу, но в .NET 8 её поспешно добавили, ибо без нее DI был совсем дохленький в плане функционала.
Из "сахара" там есть возможность указания делегата для резолва конкретного аргумента конструктора (или свойства, неважно), в то время как в стандартном DI нужно будет писать new X(sp.resolve, sp.resolve, sp.resolve....).
Короче, Autofac в целом делает жизнь намного проще, если у вас проект не самый простенький.
Божечки, да это вот "безразлично" на беке существует в каждом слое, между слоями, и вообще называется слабой связностью.
Вот ты и попался.
Ох уж эти свидетели "ии зохватет мир".
Мне кажется, что так уже никто не делает. Данные утеряются при рестарте же.
Но если при этом корзина будет в БД, то это уже не состояние?
Лайк за шрифт консоли
В таком случае, это плохие пакеты, которые плохо спроектировали. Подобный аргумент можно и раздуть дальше — например, можно сказать, что, могут существовать такие пакеты, которые складывают статичные данные вообще в файл рядом с собой. Или еще куда. Что вы будете с ними делать, вмето пересоздания процесса перезапускать весь контейнер? Или всё же признаете, что это не проблема stateless хоста?
Мне кажется, вы как-то не так понимаете stateless/serverless. Из ваших претензий я почерпываю следующее:
Вы хотите, чтобы все статические классы магически обнулились. Но, надеюсь, вы понимаете, что магии не бывает, плюс (также надеюсь) вы знаете как работает .NET, и следовательно понимаете, что для этого обнуления потребуется пересоздать AppDomain (если уж не перезапускать весь процесс).
Вы также хотите, чтобы стартап "stateless" происходил максимально быстро и негодуете на медленную скорость подъёма приложения.
Но я не вижу, как именно вы подразумеваете, как это должно произойти. Возможно, через множество подготовленных одноразовых аппдоменов? Но ведь это же ужасно расточительно, тратить 100+мс процессора, чтобы выполнить один очень быстрый и не требовательный ресурс.
Еще одно противоречение вижу в ваших словах: вы противитесь не использованию стататичных классов, но топите за "stateless". Закономерный вопрос - нафига вам статичные классы, если, по вашей логике, в "stateless" вы ожидаете, что они будут постоянно обнуляться (что довольно дорого со стороны хоста)? У вас есть ваш хендлер-метод, есть весь контекст запроса, зачем вам статика?
Понимаете к чему я, или начнёте спрашивать, мол, ну а нестатичная переменная типа тоже почему не обнулялась?
Боюсь вас снова разочаровать, но вы неправильно протестировали. Моё решение не модифицирует магически поведение статичных классов. И не предполагает, что вы будете их использовать (так же, как бы вы не использовали их в обычной современной архитектуре любого приложения).
Если вам не нужны сервисы, то вы их просто не регистрируйте. Но если (в контексте вашеих задач) они вам нужны, то вам в любом случае от них никуда не деться, с учетом того, что выше приложение постоянно выключают. Т.е. этот аргумент не играет ни в чью пользу.
Не понял. Если у вас долгоживущее приложение (из-за частых запросов), то регистрация сервисов (=стартап) как раз будет происходить лишь единожды.
После некоторых курсов это даже не джун.
А ещё на улице ветер, бывает, дует)
А что, теперь тут будет реклама в постах?
Учитывая ваш текст из статьи, описываемый вами .NET хост просто подключает вашу библиотеку к себе в аппдомен и держит его там, дёргая ваши методы через рефлексию (или кодген). Благодаря этому наблюдению у меня сложилась картина, как можно это использовать без какой-либо боли, описанной вами в статье (но я мог что-то пропустить, так что жду обратной связи)
Вот микропример того, что я имел ввиду: https://pastebin.com/bG6DyJxn
Что такой подход даёт:
App.Runможно вызывать из любых потоков, в т.ч. из нескольких одновременно.В
BuildContainerинициализируете ваш DI, этот код будет запущен лишь один раз на весь хостовый процесс/аппдомен.При любом вызове вы получаете ссылку на
IServiceProvider, который находится в скоупе, который будет успешно закрыт после выполнения вышего делегата.Как использовать: рисуете свой хендлер, внутри оборачиваете свой бизнес-код в делегат:
public class Handler{
public string FunctionHandler(int arg)
{
return App.Run(provider =>
{
// Здесь бизнес-код, все сервисы доступны через provider.
return $"Hello world_{arg}";
});
}
}
Уважаемый автор, нижайшепрошу прощения, но мне кажется, что вы
проигралипошли не туда ещё на этапе "Подготовка приложения".Дело в том, что вам стоило задуматься и (вполне закономерно) осознать, что встреченная вами ситуация не так проблематична, как кажется на первый взгляд.
Видите ли, ее можно решить написав небольшую обёртку с DI (мы же хотим красиво), поставив лок против race condition, и все красиво запаковать в минимальное количество абстракций.
В таком виде бизнес-код можно будет писать хоть прямо в этих самых "хендлерах", обернув их, разве что, в делегат.
Ах, красота. Но жаль неочевидно ни разу.
Да вроде бы именно так вы и сказали: из вашего личного опыта вы считаете наличие некоего функционала минусом. "Наличие" может быть применимо только к пакету, в котором этот функционал находится.
Это как говорить, что молоток плохой, ибо есть люди, которые им по голове бьют)
Да, допустим интерцепторы редко когда нужны, но их наличие ведь не делает библиотеку более плохой, не так ли?
NeoNN описал просто набор дополнительного сахара, но там есть и вещи, которые невозможны в принципе в стандартном DI, их туда просто еще не завезли.
Например, декораторы, или упомянутые интерцепторы.
Еще там есть очень полезная регистрация по ключу, но в .NET 8 её поспешно добавили, ибо без нее DI был совсем дохленький в плане функционала.
Из "сахара" там есть возможность указания делегата для резолва конкретного аргумента конструктора (или свойства, неважно), в то время как в стандартном DI нужно будет писать new X(sp.resolve, sp.resolve, sp.resolve....).
Короче, Autofac в целом делает жизнь намного проще, если у вас проект не самый простенький.
Таких называют эгоистами, гедонистами, "ишь удумал для себя пожить" и прочими социально-неодобрительными взглядами.
"Загадка" оказалась не в том, чтобы найти подходящее решение, а в том, чтобы угадать общепринятый ответ. Все встало на свои места :)
Надо просто сразу сходу говорить "погоди-погоди, ты, наверное, имеешь ввиду не загадку, а угадайку?" :)