Reputation: 1
I'm trying to schedule jobs with Quartz.Net. I created a simple API project, initialized Quartz in it, and connected Quartz to a PostgreSQL database to store jobs and triggers. So far, everything is good. I can create and delete new jobs, and there are no problems during execution as well.
However, while the program is running, the memory usage keeps increasing. After running for some time, depending on the number of jobs, the program throws an OutOfMemoryException and crashes.
From Rider's monitor tool, I can see that it creates services or classes and can't dispose of them, hence the memory usage increases. I tried to look at Quartz.Net's documentation and various other posts/questions but couldn't find a solution.
My API project is a base .NET API project. The only changes are the configurations below.
Used Nuget packages:
<PackageReference Include="Quartz" Version="3.13.1" />
<PackageReference Include="Quartz.AspNetCore" Version="3.13.1" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.13.1" />
<PackageReference Include="Quartz.Serialization.Json" Version="3.13.1" />
<PackageReference Include="Npgsql" Version="8.0.6" />
The configurations in appsettings.json
are below:
"ConnectionStrings": {
"DefaultConnection": "User ID=postgres;Password=postgres;Server=localhost;Port=5432;Database=postgre_db"
},
"Quartz": {
"quartz.scheduler.instanceName": "default",
"quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
"quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.PostgreSQLDelegate, Quartz",
"quartz.jobStore.tablePrefix": "QRTZ_",
"quartz.jobStore.dataSource": "default",
"quartz.dataSource.default.connectionStringName": "DefaultConnection",
"quartz.dataSource.default.provider": "Npgsql",
"quartz.jobStore.useProperties": "true",
"quartz.serializer.type": "newtonsoft"
}
Here's how I did the configurations in Program.cs
:
// Read configurations in appsettings.json
builder.Services.Configure<QuartzOptions>(builder.Configuration.GetSection("Quartz"));
// Use Quartz
builder.Services.AddQuartz(configurator =>
{
configurator.UsePersistentStore(options =>
{
options.UsePostgres(builder.Configuration.GetConnectionString("DefaultConnection")!);
options.UseNewtonsoftJsonSerializer();
});
// Create a job and trigger
JobKey jobFromProgram = new("JobFromProgram");
configurator.AddJob<SimpleJob>(jobFromProgram);
configurator.AddTrigger(trigger => trigger.ForJob(jobFromProgram)
.WithIdentity("JobFromProgramTrigger")
.WithCronSchedule("*/5 * * ? * *")); // Run every 5 seconds
});
builder.Services.AddQuartzHostedService(options =>
{
options.WaitForJobsToComplete = true;
});
And this is my Job class.
public class SimpleJob(ILogger<SimpleJob> logger) : IJob
{
public Task Execute(IJobExecutionContext context)
{
logger.LogInformation($"{context.JobDetail.Key.Name} executed! {DateTime.Now}");
return Task.CompletedTask;
}
}
When the program is run with this setup, triggers are read from the database and jobs are executed. There is one job in this setup and it executes every 2 seconds. However, each time the job is executed, the memory usage increases without any decrease in time, until it crashes the program.
I also tried to create a custom JobFactory class, and tried to use that:
public class SimpleJobFactory(IServiceProvider serviceProvider) : IJobFactory
{
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return (IJob)serviceProvider.GetRequiredService(bundle.JobDetail.JobType);
}
public void ReturnJob(IJob job) { }
}
// In Program.cs, in the AddQuartz section I used it like this:
configurator.UseJobFactory<SimpleJobFactory>();
I also tried to register job-jobfactory classes and IScheduler as a singleton:
builder.Services.AddSingleton<SimpleJob>().AddSingleton<SimpleJobFactory>();
builder.Services.AddSingleton(provider => provider.GetRequiredService<ISchedulerFactory>().GetScheduler().GetAwaiter().GetResult());
but those attemps didn't work either. And at this point, I can't figure out what's wrong
Upvotes: 0
Views: 95