Вопрос о времени жизни внедрения зависимостей в функции Azure V3

Я использую Функции Azure v3 и DI. У меня есть служба, которую я настраиваю с временным временем жизни в моем StartUp.cs (используя: builder.Services.AddTransient<ICoreApiClient>(s => coreApiService);), а затем внедряю в свой класс функций Azure. Функция Azure - это функция триггера очереди хранилища.

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

Я ожидаю получить отдельный экземпляр для каждого вызова или выполнения неверно? Проблема, с которой я сталкиваюсь, заключается в том, что _coreApiClient, похоже, используется для нескольких вызовов метода Run, поэтому я устанавливаю в нем свойства (например, идентификатор клиента или ключ API и т. Д.), Которые действительны для одного сообщения и должны оставаться для обработка этого сообщения меняется, когда начинается обработка следующего сообщения.

Я делаю это неправильно или не понимаю время жизни должным образом?

Вот мой код запуска:

public class Startup: FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddLogging();
            
            var loggingService = new HttpLoggingService(Environment.GetEnvironmentVariable("LoggingURL"), 0, "ABC.Integrations");
            builder.Services.AddTransient<ILoggingService>(s => loggingService);

            int CoreApiTimeout = 60;  //Environment.GetEnvironmentVariable("CoreApiTimeout")
            var coreApiService = new CoreApiClient(Environment.GetEnvironmentVariable("CoreApiKey"),string.Empty, CoreApiTimeout,Environment.GetEnvironmentVariable("CoreApiBaseUrl"));
            builder.Services.AddTransient<ICoreApiClient>(s => coreApiService);
           
        }
    }

И мой класс функций Azure:

public class TaskRouter
    {
        private readonly ICoreApiClient _coreApiClient;
        private readonly ILoggingService _upgLogger;
        private readonly ILogger<TaskRouter> _log;        

        public TaskRouter(ICoreApiClient coreApiClient, ILoggingService upgLogger, ILogger<TaskRouter> log)
        {
            _coreApiClient = coreApiClient;
            _upgLogger = upgLogger;
            _log = log;
            
        }

        [FunctionName("RouteTask")]
        [ExponentialBackoffRetry(5, "00:00:04", "00:03:00")]
        public async Task Run([QueueTrigger("task-scheduler", Connection = "")]
            string queueItem)
        {

            
                //Call Appropriate Function to start task
                var taskMsg = JsonConvert.DeserializeObject<TaskMessage>(queueItem);
                                
                _coreApiClient.SetId(taskMsg.TaskNumber);
                
                //DO SOME WORK HERE
                
                Console.Log(_coreApiClient.GetId);  //Will be different b/c this was set by the next message
        }
   }

person Jason    schedule 28.02.2021    source источник


Ответы (1)


Хотя клиент зарегистрирован как временный в контейнере, на самом деле это синглтон, поскольку экземпляр, созданный в Startup, является единственным экземпляром, который когда-либо будет возвращен для каждого вызова для инъекции ICoreApiClient.

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

//...

builder.Services.AddTransient<ICoreApiClient>(s => 
    new CoreApiClient(Environment.GetEnvironmentVariable("CoreApiKey"), string.Empty, CoreApiTimeout, Environment.GetEnvironmentVariable("CoreApiBaseUrl"))
);

//...
person Nkosi    schedule 28.02.2021
comment
Ах, большое вам спасибо - вот в чем проблема. Очень логично и кажется очевидным в ретроспективе, но я смотрел на это часами и не осознавал этого. Спасибо!! - person Jason; 01.03.2021