jamesmh / coravel

Near-zero config .NET library that makes advanced application features like Task Scheduling, Caching, Queuing, Event Broadcasting, and more a breeze!
https://docs.coravel.net/Installation/
MIT License
3.82k stars 252 forks source link

Fluent configurations #399

Open BOBx5 opened 1 week ago

BOBx5 commented 1 week ago

AS-IS

Currently, To use Coravel Queue, I have to use functions below

public void ConfigureServices(IServiceCollection services)
{
    services.AddQueue();
}
public static IApplicationBuilder UseCoravel(this IApplicationBuilder app)
{
    app.ApplicationServices.ConfigureQueue();
    return app;
}

TO-BE

1. Queue Consumption Delay with milliseconds

For better customizable options, I propose that the delay time can be set with milliseconds.

QueuingHost.cs

2. Add Extension Method for Queue Consummation Delay (or other options)


public void ConfigureServices(IServiceCollection services)
{
    services.AddQueue()
        .WithConsummationDelay(1000); // 1 second
}
jamesmh commented 1 week ago

You can already set the consummation delay from your appsettings.json file -> https://docs.coravel.net/Queuing/#adjusting-consummation-delay.

This would definitely be a breaking change, since right now in that file 1 represents 1 second. So we'd need to figure out what the migration path would be.

Any ideas on how we could change the delay to use ms but not break existing usages of this feature?

BOBx5 commented 1 week ago

What if add configuration property on Coravel:Queue:ConsummationDelayUnit ?

Modify QueuingHost.cs like below:


internal class QueuingHost : IHostedService, IDisposable
{

    private IConfiguration _configuration;
    // ...

    public Task StartAsync(CancellationToken cancellationToken)
    {
        TimeSpan consummationDelay = GetConsummationDelay();

        this._timer = new Timer((state) => this._signal.Release(), null, TimeSpan.Zero, consummationDelay);
        Task.Run(ConsumeQueueAsync);
        return Task.CompletedTask;
    }

    // Change return type from `int` to `TimeSpan` 
    private TimeSpan GetConsummationDelay()
    {
        string delayUnit = GetConsummationDelayUnit();
        int delayValue = GetConsummationDelayValue(delayUnit);

        switch (delayUnit)
        {
            case "Milliseconds":
                return TimeSpan.FromMilliseconds(delayValue);
            case "Seconds":
            default:
                return TimeSpan.FromSeconds(delayValue);
        }
    }

    // Get delay unit ("Milliseconds" or "Seconds").
    // This can be improved by using an enum.
    private string GetConsummationDelayUnit()
    {
        var delayUnitSection = this._configuration.GetSection("Coravel:Queue:ConsummationDelayUnit");
        return delayUnitSection.Value ?? "Seconds";
    }

    private int GetConsummationDelayValue(string delayUnit)
    {
        var delayValueSection = this._configuration.GetSection("Coravel:Queue:ConsummationDelay");
        if (int.TryParse(delayValueSection.Value, out int parsedDelay))
        {
            return parsedDelay;
        }

        switch (delayUnit)
        {
            case "Milliseconds":
                return 30000;

            case "Seconds":
            default:
                return 30;
        }
    }
}
jamesmh commented 1 week ago

Cool. Do you want to create an PR for this?

Could you also add some tests for these methods? You can make the new method public and test it in the unit test project by adding something like this to the top of the class: [assembly:InternalsVisibleTo("NameOfYourUnitTestProject")].

Thanks!