coravel icon indicating copy to clipboard operation
coravel copied to clipboard

Dependency injection for job with parameters

Open felpel opened this issue 2 years ago • 3 comments

Describe the bug I'm trying to setup dependency injection for a new scheduled job with parameters and followed the following documentation section, without much success.

In my Program.cs class, I do the following for registration:

services.AddTransient<MyJob>();

For the MyJob class, the single parameter (e.g. MyParams) is right after other injected dependencies.

On startup, here's the strack trace I get:

Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MyNamespace.MyJob Lifetime: Transient ImplementationType: MyNamespace.MyJob': Unable to resolve service for type 'MyNamespace.MyParams' while attempting to activate 'MyNamespace.MyJob'.)

Affected Coravel Feature Scheduling, but it could apply to other features as well

Expected behaviour I'm unsure whether I'm missing a step here or if the registration is incorrect, but I shall be capable of registering jobs with parameters 😄

Note that I'm running on .NET 6, which might have an impact, but I don't know for sure, and Coravel being at the latest version.

felpel avatar Nov 21 '21 20:11 felpel

Did you call ScheduleWithParams<MyJob>() in your configuration too?

jamesmh avatar Nov 22 '21 13:11 jamesmh

Did you call ScheduleWithParams<MyJob>() in your configuration too?

Regarding this, it may lead to another question I had regarding this library. Is it possible to inject IScheduler within a class and schedule on-demand jobs? Within a class registered for dependency injection, IScheduler is injected in it like such:

public class MyService 
{
      private readonly IScheduler _scheduler;

      public MyService(IScheduler scheduler) 
      {
           _scheduler = scheduler;
      }

      public async Task SomeMethodAsync()
      {
              // Parameters may be created here or passed to the current method, for instance
               MyParams parameters = new();

               // some asynchronous logic
 
               _scheduler
                     .ScheduleWithParams<MyJob>(parameters)
                     .Every30Minutes();
      }
}

For context, I have the following workflow that I would like to do in my app:

  • Every 30 minutes, I have a look at my calendar for time-bounded events
  • If an event started on time, I shall track the event for inner events every 5 minutes and the previous scheduling shall be unregistered
  • Once the aforementioned event ends, then the scheduling would be unregistered

felpel avatar Nov 22 '21 15:11 felpel

So it's not an officially a public thing (yet?), but it's possible if you really want to - check out this issue for some specifics: https://github.com/jamesmh/coravel/issues/77

jamesmh avatar Dec 24 '21 15:12 jamesmh

Got the same issue here.

Jofrais avatar Apr 01 '23 13:04 Jofrais

I figured it out. When you call ScheduleWithParams<T>, you don't need to register it as a transient just like the documentation said at this part : https://docs.coravel.net/Invocables/#manually

Coravel actually resolve all the dependency by itself (wich is really great stuff).

Maybe adding this to the documentation could help some people who got the same issue.

Jofrais avatar Apr 03 '23 15:04 Jofrais

I figured it out. When you call ScheduleWithParams<T>, you don't need to register it as a transient just like the documentation said at this part : https://docs.coravel.net/Invocables/#manually

Coravel actually resolve all the dependency by itself (wich is really great stuff).

Maybe adding this to the documentation could help some people who got the same issue.

@Jofrais, I had the same experience. @jamesmh is this expected behavior contrary to documentation?

Kevinf63 avatar May 16 '23 22:05 Kevinf63

This has to do with how this code path creates/instantiates the object/invocable. Is it expected? No lol. I can see why it's the case though. Will have to investigate if there's a way to do this via the service container to keep the experience consistent, or if not then make that an explicit difference called out in the docs.

jamesmh avatar May 17 '23 02:05 jamesmh

@jamesmh thanks for the prompt response.

Kevinf63 avatar May 17 '23 08:05 Kevinf63

Same issue for me too, solved like @Jofrais

Hiden46 avatar Jun 15 '23 07:06 Hiden46

Will close for now. Might revisit but for now it works with the disclaimer to not register to DI.

Added something in the docs around this.

jamesmh avatar Aug 18 '23 03:08 jamesmh