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.91k stars 257 forks source link

Coravel Background Service #317

Closed DLarner closed 2 months ago

DLarner commented 1 year ago

Hi, I have implemented Coravel quite successfully and is working great. I have a couple of issues which is probably something I'm not doing right. My code is below. The queries are:

  1. The OnError is not working, this line is not being called when starting the application so therefore any errors are not captured by this global error routine. Can you see why?
  2. I have commented out the following line and the task still runs. Would you expect this? The reason why I have commented this line out is that it was causing an error: Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: PricingUpdateController Lifetime: Transient ImplementationType: PricingUpdateController': Unable to resolve service for type 'System.Boolean' while attempting to activate 'PricingUpdateController'.)

Any help or guidance would be appreciated. Thanks and here is my relevant code:

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureLogging(
       loggingBuilder =>
       {
           var configuration = new ConfigurationBuilder()
                   .AddJsonFile("appsettings.json")
                   .Build();
       })
    .ConfigureServices(services =>
    {
        services.AddSingleton(new CommandLineArgs() { Args = args });
        services.AddHostedService<Worker>();
        services.AddApplicationInsightsTelemetryWorkerService();
        services.AddScheduler();
        //services.AddTransient<PricingUpdateController>();
    })
    .Build();

host.Services.UseScheduler(scheduler =>
{
    scheduler.ScheduleWithParams<PricingUpdateController>(false, false, false, true, true, true, false, false).EveryThirtySeconds().PreventOverlapping("PricingUpdateController");
})
.OnError(exception => LogController.Instance.LogText(exception.Message));

await host.RunAsync();
jamesmh commented 1 year ago

So I'd uncomment the line with //services.AddTransient<PricingUpdateController>();.

The original exception you were getting Error while validating the service descriptor... means that the constructor of your PricingUpdateController has a mismatch with the parameter you supplied (e.g. the 8 booleans - does your PricingUpdateController class have a constructor with exactly 8 booleans?)

If you need more help could you past the constructor method signatures (not the body) for the PricingUpdateController class?

Thanks!

DLarner commented 1 year ago

Hi James,

Thanks for the prompt response. Here is my constructor etc.

internal class PricingUpdateController : IInvocable
{
    public bool testSystem;
    public bool calculateStones;
    public bool calculateProducts;
    public bool calculateMetals;
    public bool calculateProductGroupMounts;
    public bool calculateOrders;
    public bool calculateInvoices;
    public bool checkStockAvailable;

    public PricingUpdateController(bool TestSystem, bool calculateStones, bool calculateProducts, bool calculateMetals, bool calculateProductGroupMounts, bool calculateOrders, bool calculateInvoices, bool checkStockAvailable)
    {
        this.testSystem = TestSystem;
        this.calculateStones = calculateStones;
        this.calculateProducts = calculateProducts;
        this.calculateMetals = calculateMetals;
        this.calculateProductGroupMounts = calculateProductGroupMounts;
        this.calculateOrders = calculateOrders;
        this.calculateInvoices = calculateInvoices;
        this.checkStockAvailable = checkStockAvailable;
    }

    public System.Threading.Tasks.Task Invoke()
    {

From: James Hickey @.> Sent: 04 December 2022 01:13 To: jamesmh/coravel @.> Cc: Darren Larner @.>; Author @.> Subject: Re: [jamesmh/coravel] Coravel Background Service (Issue #317)

So I'd uncomment the line with //services.AddTransient();.

The original exception you were getting Error while validating the service descriptor... means that the constructor of your PricingUpdateController has a mismatch with the parameter you supplied (e.g. the 8 booleans - does your PricingUpdateController class have a constructor with exactly 8 booleans?)

If you need more help could you past the constructor method signatures (not the body) for the PricingUpdateController class?

Thanks!

— Reply to this email directly, view it on GitHubhttps://github.com/jamesmh/coravel/issues/317#issuecomment-1336293173, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AD36WZL7Z6ZKHUIBMFQCBSLWLPVZ5ANCNFSM6AAAAAASS44JEA. You are receiving this because you authored the thread.Message ID: @.**@.>>

jamesmh commented 1 year ago

For fun, try making the class public instead of internal? Let me know what happens 🤔

DLarner commented 1 year ago

Yes I did try that and it didn’t work! This is the full exception. Thanks

System.AggregateException HResult=0x80131500 Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: HMSystemWorkflowService.Controllers.PricingUpdateController Lifetime: Transient ImplementationType: HMSystemWorkflowService.Controllers.PricingUpdateController': Unable to resolve service for type 'System.Boolean' while attempting to activate 'HMSystemWorkflowService.Controllers.PricingUpdateController'.) Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection1 serviceDescriptors, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder) at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter1.CreateServiceProvider(Object containerBuilder) at Microsoft.Extensions.Hosting.HostBuilder.InitializeServiceProvider() at Microsoft.Extensions.Hosting.HostBuilder.Build() at Program.<

$>d__0.MoveNext() in C:\Users\darre\source\repos\HMSystem\HMSystemWorkflowService\Program.cs:line 10

This exception was originally thrown at this call stack: Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain, System.Reflection.ParameterInfo[], bool) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ResultCache, System.Type, System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Microsoft.Extensions.DependencyInjection.ServiceDescriptor, System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain, int) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Microsoft.Extensions.DependencyInjection.ServiceDescriptor, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain) Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(Microsoft.Extensions.DependencyInjection.ServiceDescriptor)

Inner Exception 1: InvalidOperationException: Error while validating the service descriptor 'ServiceType: HMSystemWorkflowService.Controllers.PricingUpdateController Lifetime: Transient ImplementationType: HMSystemWorkflowService.Controllers.PricingUpdateController': Unable to resolve service for type 'System.Boolean' while attempting to activate 'HMSystemWorkflowService.Controllers.PricingUpdateController'.

Inner Exception 2: InvalidOperationException: Unable to resolve service for type 'System.Boolean' while attempting to activate 'HMSystemWorkflowService.Controllers.PricingUpdateController'.

From: James Hickey @.> Sent: 04 December 2022 01:18 To: jamesmh/coravel @.> Cc: Darren Larner @.>; Author @.> Subject: Re: [jamesmh/coravel] Coravel Background Service (Issue #317)

For fun, try making the class public instead of internal? Let me know what happens 🤔

— Reply to this email directly, view it on GitHubhttps://github.com/jamesmh/coravel/issues/317#issuecomment-1336294232, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AD36WZI7OZYO44JGTRAYXJLWLPWOLANCNFSM6AAAAAASS44JEA. You are receiving this because you authored the thread.Message ID: @.**@.>>

jamesmh commented 1 year ago

So I can confirm your first comments - commenting out the //services.AddTransient<PricingUpdateController>(); makes this work. Otherwise, something is amiss...

I tried adding some unit tests in the main project against this case - and they pass. Yet, when I create a new real-life .NET project similar to yours, then I am getting the same exception lol.

And you are correct that this is not expected behaviour. This happens with other constructor types like integers, strings, etc. And also only when one param is present.

I suspect this is something to do with .NET 7 or some new DI stuff that Microsoft changed under the covers (not the first time this happened!)

I'll look into this - but for now just don't register the invocable and it seems like it works 🤔

DLarner commented 1 year ago

No problem, thanks for looking into this. Just to clarify, I am currently running this on .Net 6.

Any ideas on my other issue with the global OnError not working?

From: James Hickey @.> Sent: 04 December 2022 02:06 To: jamesmh/coravel @.> Cc: Darren Larner @.>; Author @.> Subject: Re: [jamesmh/coravel] Coravel Background Service (Issue #317)

So I can confirm your first comments - commenting out the //services.AddTransient(); makes this work. Otherwise, something is amiss...

I tried adding some unit tests in the main project against this case - and they pass. Yet, when I create a new real-life .NET project similar to yours, then I am getting the same exception lol.

And you are correct that this is not expected behaviour. This happens with other constructor types like integers, strings, etc. And also only when one param is present.

I suspect this is something to do with .NET 7 or some new DI stuff that Microsoft changed under the covers (not the first time this happened!)

I'll look into this - but for now just don't register the invocable and it seems like it works 🤔

— Reply to this email directly, view it on GitHubhttps://github.com/jamesmh/coravel/issues/317#issuecomment-1336301521, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AD36WZLBZUVC7UYYWGAOWKTWLP4ADANCNFSM6AAAAAASS44JEA. You are receiving this because you authored the thread.Message ID: @.**@.>>

jamesmh commented 1 year ago

For OnError -> try throwing an exception from inside your invocable's Invoke method. It should trigger.

DLarner commented 1 year ago

It’s just being ignored for some reason. Here is a screenshot:

@.***

From: James Hickey @.> Sent: 04 December 2022 02:24 To: jamesmh/coravel @.> Cc: Darren Larner @.>; Author @.> Subject: Re: [jamesmh/coravel] Coravel Background Service (Issue #317)

For OnError -> try throwing an exception from inside your invocable's Invoke method. It should trigger.

— Reply to this email directly, view it on GitHubhttps://github.com/jamesmh/coravel/issues/317#issuecomment-1336304108, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AD36WZIT75PQXSAO7NPQ52TWLP6E7ANCNFSM6AAAAAASS44JEA. You are receiving this because you authored the thread.Message ID: @.**@.>>

esskar commented 1 year ago

What happens if you update your controller like

public record PricingUpdateControllerConfiguration(
    bool TestSystem;
    bool CalculateStones;
    bool CalculateProducts;
    bool CalculateMetals;
    bool CalculateProductGroupMounts;
    bool CalculateOrders;
    bool CalculateInvoices;
    bool CheckStockAvailable);

public class PricingUpdateController : IInvocable
{
    private readonly PricingUpdateControllerConfiguration _configuration;

    public PricingUpdateController(PricingUpdateControllerConfiguration configuration)
    {
         _configuration = cofiguration;
    }

    // ...
}

and call it with

host.Services.UseScheduler(scheduler =>
{
    scheduler.ScheduleWithParams<PricingUpdateController>(
        new PricingUpdateControllerConfiguration(false, false, false, true, true, true, false, false)
    ).EveryThirtySeconds().PreventOverlapping(nameof(PricingUpdateController));
})
jamesmh commented 2 months ago

Closing - please let me know if there's still ongoing issues with this.

DLarner commented 2 months ago

Hi James,

Don’t seem to have had any issues since. Thanks for checking.

Have you got a changelog for v6 you have just released please?

Regards Darren

From: James Hickey @.> Sent: 26 September 2024 20:57 To: jamesmh/coravel @.> Cc: Darren Larner @.>; Author @.> Subject: Re: [jamesmh/coravel] Coravel Background Service (Issue #317)

Closed #317https://github.com/jamesmh/coravel/issues/317 as completed.

— Reply to this email directly, view it on GitHubhttps://github.com/jamesmh/coravel/issues/317#event-14421908239, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AD36WZNEQNGQUN4ME7ANHPLZYRRHNAVCNFSM6AAAAABO5XTZOWVHI2DSMVQWIX3LMV45UABCJFZXG5LFIV3GK3TUJZXXI2LGNFRWC5DJN5XDWMJUGQZDCOJQHAZDGOI. You are receiving this because you authored the thread.Message ID: @.**@.>>