0

Not getting updated state of configuration using IOptionsSnapshot or IOptionsMonitor, using .net6 and Worker Service template.

I've started testing with Workers in .net6.

My problem is that I've been working in the configuration settings and all was good... until I needed to get the updated state of my configuration file to delay or continue with the process my Worker has to do.

This are my code files:

Program.cs

var builder = Host.CreateDefaultBuilder();

// Config
builder.ConfigureAppConfiguration((hostBuilderContext, configurationBuilder) =>
{
    configurationBuilder.AddJsonFile(
        ConfigurationConstants.AppSettingsFileLocation,
        optional: false,
        reloadOnChange: true
    );

    var env = hostBuilderContext.HostingEnvironment;
    configurationBuilder
        .AddJsonFile(
            ConfigurationConstants.AppSettingsFileLocation,
            optional: false,
            reloadOnChange: true
        )
        .AddJsonFile(
            $"./Configuration/environments/environment.{env.EnvironmentName}.json",
            optional: false,
            reloadOnChange: true
        );

    var configuration = configurationBuilder.Build();
});

// Services
builder.ConfigureServices((hostBuilderContext, services) =>
{
    services.AddHostedService<Worker>();
    services.AddScoped<MessageRouterProcess, MessageRouterProcess>();
    services.AddTransient<IQueueManager, RabbitMQQueueManagerAdapter>();

    services.Configure<WorkerConfiguration>(hostBuilderContext.Configuration.GetSection(nameof(WorkerConfiguration)));
});

var host = builder.Build();

await host.RunAsync();

Worker.cs

This runs the Business logic Service which is "MessageRouterProcess.cs"

namespace Meloons.Whatsapp.Worker.MessageRouter
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        public IServiceProvider Services { get; }

        public Worker(
            IServiceProvider serviceProvider,
            ILogger<Worker> logger
        )
        {
            Services = serviceProvider;
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Consume Scoped Service Hosted Service running.");

            await DoWork(stoppingToken);
        }

        private async Task DoWork(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Consume Scoped Service Hosted Service is working.");

            using (var scope = Services.CreateScope())
            {
                var scopedProcessingService =
                    scope.ServiceProvider
                        .GetRequiredService<MessageRouterProcess>();

                await scopedProcessingService.RouteMessages();
            }
        }
    }
}

Business Logic

MessageRouterProcess.cs

In this file, inside the while loop, I have this validation: "if (!this.Configuration.Lecture)". This gets a Config value and based on this value, my worker is going to delay and skip the current iteration of the loop (so the business logic is not going to execute) or is going to run all the process.

namespace Meloons.Whatsapp.WebAPI.Core
{
    public class MessageRouterProcess
    {
        protected WorkerConfiguration Configuration;
        private IQueueManager queueManager;

        private readonly HttpClient _httpClient;

        public MessageRouterProcess(
            IQueueManager queueManager,
            IOptionsMonitor<WorkerConfiguration> configuration
        )
        {
            this.Configuration = configuration.CurrentValue;
            configuration.OnChange(updatedConfig =>
            {
                this.Configuration = updatedConfig;
            });

            this.queueManager = queueManager;
            _httpClient = new HttpClient();
        }

        public async Task RouteMessages()
        {
            while (true)
            {
                //bool lecture = bool.Parse(Configuration.GetSection("WorkerConfiguration")["Lecture"]);
                //int TPS = int.Parse(Configuration.GetSection("WorkerConfiguration")["TPS"]);
                //string OutboundQueue = Configuration.GetSection("WorkerConfiguration")["OutboundQueue"];

                if (!this.Configuration.Lecture)
                {
                    await Task.Delay(1000);
                    continue;
                };

                var messageAmountToConsume = this.Configuration.TPS; // Start amount
                var now = DateTime.UtcNow;

                List<Message> messages = await this.queueManager.FetchItem<Message>(messageAmountToConsume);

                this.queueManager.Publish(messages, this.Configuration.OutboundQueue);

                var endDate = DateTime.UtcNow;

                TimeSpan timestamp = endDate - now;
                int timeGap = (int)timestamp.TotalMilliseconds;

                if (1000 - timeGap > 0)
                    await Task.Delay(1000 - timeGap);
            }
        }
    }
}

In this case my code is using IOptionsMonitor (not working), but in the past I've tried with IOptionsSnapshot too and is not working either.

I'll keep looking what is happening but I'll thank so much to know your opinion on this, and to knowing what I'm forgetting.

Thanks :D

0 Answers0