We need to configure Quartz to use SQL storage, but we can not store the connection string in the static quartz.config file. In the AbpQuartzModule.PreInitialize() the AbpQuartzConfiguration is registred to resolve from the StdSchedulerFactory.GetDefaultScheduler(), but we would need to register our own implementation of IAbpQuartzConfiguration to create a scheduler with our configuration.
class AbpCustomQuartzConfiguration : IAbpQuartzConfiguration
{
public IScheduler Scheduler
{
get
{
var builder = SchedulerBuilder.Create();
builder.UsePersistentStore(options =>
{
options.UseClustering();
options.UseSqlServer(sqlServerOptions =>
{
sqlServerOptions.ConnectionString = "...";
});
options.UseSerializer<JsonObjectSerializer>();
});
builder.SchedulerId = StdSchedulerFactory.AutoGenerateInstanceId;
builder.MisfireThreshold = TimeSpan.FromMinutes(5);
var scheduler = builder.BuildScheduler().Result;
scheduler.JobFactory = new AbpQuartzJobFactory(IocManager.Instance);
scheduler.ListenerManager.AddJobListener(IocManager.Instance.Resolve<IJobListener>());
return scheduler;
}
}
}
How can we accomplish this?
- Version: Abp 5.14
- Framework: .NET Core
6 Answer(s)
-
0
Hi ivanosw1 You can use
Configuration.ReplaceService<TInterface,TImplemention>to replace the registration. e.g.public class YourModule : AbpModule { public override void PreInitialize() { Configuration.ReplaceService<IAbpQuartzConfiguration, AbpCustomQuartzConfiguration>(); } }Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi Zony, if I use the
ReplaceServicethe registred type is still overwritten byAbp.Quartzand thus the
IScheduleris not properly configred. Am I missing something?Furhermore, the
Abp.Quartz.PreInitializecalls indirectly theStdSchedulerFactory.GetDefaultScheduler(), resulting in the creation of a default in-memory sheduler even before my customPreInitializegets called. In this way I will end up with 2 different scheduler instances.Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
-
0
Hi, this registration does work, but from the logs I can confirm the suspect that 2 different schedulers are initialized:
... INFO 2021-01-08 09:33:15,969 [1 ] Quartz.Impl.StdSchedulerFactory - Default Quartz.NET properties loaded from embedded resource file INFO 2021-01-08 09:33:16,021 [1 ] Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl INFO 2021-01-08 09:33:16,027 [1 ] Quartz.Core.QuartzScheduler - Quartz Scheduler v.3.0.7.0 created. INFO 2021-01-08 09:33:16,028 [1 ] Quartz.Simpl.RAMJobStore - RAMJobStore initialized. INFO 2021-01-08 09:33:16,030 [1 ] Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v3.0.7.0) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'Quartz.Simpl.DefaultThreadPool' - with 10 threads. Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistence. and is not clustered. INFO 2021-01-08 09:33:16,034 [1 ] Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized INFO 2021-01-08 09:33:16,034 [1 ] Quartz.Impl.StdSchedulerFactory - Quartz scheduler version: 3.0.7.0 INFO 2021-01-08 09:33:16,034 [1 ] Quartz.Core.QuartzScheduler - JobFactory set to: Abp.Quartz.AbpQuartzJobFactory WARN 2021-01-08 09:33:21,647 [1 ] tion.Repositories.EphemeralXmlRepository - Using an in-memory repository. Keys will not be persisted to storage. WARN 2021-01-08 09:33:21,648 [1 ] taProtection.KeyManagement.XmlKeyManager - Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when application exits. INFO 2021-01-08 09:33:24,436 [1 ] Quartz.Util.DBConnectionManager - Registering datasource 'UnoInsDataSource' with db provider: 'Quartz.Impl.AdoJobStore.Common.DbProvider' INFO 2021-01-08 09:33:24,440 [1 ] Quartz.Impl.StdSchedulerFactory - Using object serializer: Quartz.Simpl.JsonObjectSerializer, Quartz.Serialization.Json INFO 2021-01-08 09:33:25,304 [9 ] Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl INFO 2021-01-08 09:33:25,305 [9 ] Quartz.Core.QuartzScheduler - Quartz Scheduler v.3.0.7.0 created. INFO 2021-01-08 09:33:25,311 [9 ] Quartz.Impl.AdoJobStore.JobStoreTX - Detected usage of SqlServerDelegate - defaulting 'selectWithLockSQL' to 'SELECT * FROM QRTZ_LOCKS WITH (UPDLOCK,ROWLOCK) WHERE SCHED_NAME = 'Framework Scheduler' AND LOCK_NAME = @lockName'. INFO 2021-01-08 09:33:25,311 [9 ] Quartz.Impl.AdoJobStore.JobStoreTX - Using db table-based data access locking (synchronization). INFO 2021-01-08 09:33:25,314 [9 ] Quartz.Impl.AdoJobStore.JobStoreTX - JobStoreTX initialized. INFO 2021-01-08 09:33:25,314 [9 ] Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v3.0.7.0) 'Framework Scheduler' with instanceId 'DEV-N00015.637456916052992244' Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'Quartz.Simpl.DefaultThreadPool' - with 10 threads. Using job-store 'Quartz.Impl.AdoJobStore.JobStoreTX' - which supports persistence. and is clustered. ...The
Abp.Quartzindeed creates a default scheduler regardless of what I do in myPreInitializepublic class AbpQuartzModule : AbpModule { public override void PreInitialize() { IocManager.Register<IAbpQuartzConfiguration, AbpQuartzConfiguration>(); // this line creates the default in-memory scheduler even if i replace the IAbpQuartzConfiguration in my PreInitialize Configuration.Modules.AbpQuartz().Scheduler.JobFactory = new AbpQuartzJobFactory(IocManager); }For the moment I am going to shut the default one down before replacing it with my own.
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
This seems to be a cleaner solution
[DependsOn(typeof(AbpQuartzModule))] public class MyModule : AbpModule { public MyModule() { // patch configuration before PreInitialize. // Do not use IocManager property in the constructor as it is not populated Abp.Dependency.IocManager.Instance.IocContainer.Register( Component .For<IAbpQuartzConfiguration, QuartzStartupConfiguration>() .LifestyleSingleton() .IsDefault()); } // .. }Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @ivanosw1,
Thank you for sharing this :)
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image)
