NCronJob-Dev / NCronJob

A Job Scheduler sitting on top of IHostedService in dotnet.
https://docs.ncronjob.dev/
MIT License
158 stars 11 forks source link

Multiple job types - one gets run twice if added during runtime #139

Closed vrohak closed 6 days ago

vrohak commented 6 days ago

Describe the bug

I have an IHostedService running in a Host app and want to be able to schedule recurring jobs during its runtime. Jobs can be of multiple types (for simplicity, let's call them XJob and YJob, where both implement the IJob interface).

According to my current understanding, all job types should be registered during startup, like mentioned here:

builder.Services.AddNCronJob(b => b
    .AddJob<XJob>()
    .AddJob<YJob>()
);

What I have noticed is that the one registered first (in this case XJob) gets run twice if I also add jobs through IRuntimeJobRegistry during runtime like this:

_runtimeJobRegistry.AddJob(n =>
{
     n.AddJob<XJob>(j => j.WithCronExpression("* * * * *"));
});

_runtimeJobRegistry.AddJob(n =>
{
     n.AddJob<YJob>(j => j.WithCronExpression("0,15,30,45 * * * *"));
});

Minimal Reproducible Example: https://github.com/vrohak/ncronjob-bug-demo-1.git

NOTE: everything works fine if I add both jobs together like this:

_runtimeJobRegistry.AddJob(n =>
{
     n.AddJob<XJob>(j => j.WithCronExpression("* * * * *"))
      .AddJob<YJob>(j => j.WithCronExpression("0/2 * * * *"));
});

Current behavior

Logs:

info: NCronJob.QueueWorker[398746686] New queue added for job type NCronJobBugDemo1.Jobs.XJob. info: NCronJob.QueueWorker[1048409946] Job added to queue: XJob at 11/15/2024 23:17:00 info: NCronJob.QueueWorker[1048409946] Job added to queue: XJob at 11/15/2024 23:17:00 info: NCronJob.QueueWorker[398746686] New queue added for job type NCronJobBugDemo1.Jobs.YJob. info: NCronJob.QueueWorker[1048409946] Job added to queue: YJob at 11/15/2024 23:30:00 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.

info: NCronJob.QueueWorker[1034012635] Job removed from queue: XJob at 11/15/2024 23:17:00 info: NCronJob.QueueWorker[1048409946] Job added to queue: XJob at 11/15/2024 23:18:00 Job X was executed. info: NCronJob.QueueWorker[1034012635] Job removed from queue: XJob at 11/15/2024 23:17:00 info: NCronJob.QueueWorker[1048409946] Job added to queue: XJob at 11/15/2024 23:18:00 Job X was executed.

As you can see XJob gets executed twice, while YJob runs only once.

Expected behavior

It would be great if we had an agreed upon way of registering just the job types on startup so we can schedule the actual jobs during runtime.

Until then, adding jobs during runtime should at least be possible one by one, without causing duplication.

Version information

linkdotnet commented 6 days ago

Hey @vrohak

Thanks for reporting the issue.

According to my current understanding, all job types should be registered during startup

That is correct. As we utilize the DI container, there are certain downsides and risks if the object doesn't live inside the container (trimming and performance would be some of the things).

In any case, as you "only" registering the type, that shouldn't lead to duplicated executions. That is clearly a bug.

linkdotnet commented 6 days ago

I have a fix and will push a preview version soon

linkdotnet commented 6 days ago

There will be a 3.3.6-preview packages in a few minutes. A stable release will also come soon