Coder Social home page Coder Social logo

quartznet / quartznet Goto Github PK

View Code? Open in Web Editor NEW
6.2K 310.0 1.7K 29.54 MB

Quartz Enterprise Scheduler .NET

Home Page: http://www.quartz-scheduler.net/

License: Apache License 2.0

C# 61.71% Batchfile 0.01% Shell 0.06% JavaScript 35.76% HTML 0.38% TypeScript 0.30% CSS 0.16% Dockerfile 0.05% TSQL 1.29% Less 0.11% SCSS 0.12% PowerShell 0.06%
c-sharp dotnet scheduler scheduling scheduled-tasks scheduled-jobs cron quartz nuget job-scheduler

quartznet's Introduction

Downloads Build status NuGet NuGet pre-release MyGet pre-release Join the chat at https://gitter.im/quartznet/quartznet

Quartz.NET - Enterprise Job Scheduler

Please visit https://www.quartz-scheduler.net/ for up to date news and documentation.

Compatibility

Quartz.NET supports .NET Core/netstandard 2.0 and .NET Framework 4.6.2 and later.

Installation

Building

  • You can build the code by running build.cmd (Windows) or build.sh (*nix platform)
  • You need MSBuild 17 and .NET Core SDK 6.0 to build

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License here.

For API documentation, please refer to Quartz.NET site.

quartznet's People

Contributors

amazing-andrew avatar arturdorochowicz avatar cknightdevelopment avatar codedrop avatar danielmarbach avatar drakoonic avatar drieseng avatar drusellers avatar dvdwouwe avatar exg906 avatar footcha avatar jafin avatar jvilalta avatar lahma avatar mjrousos avatar nathanbaulch avatar nunomaia avatar olicooper avatar philr avatar puddlewitt avatar ramonsmits avatar sean-gilliam avatar seanfarrow avatar senthilkumarmohan avatar sergeyshaykhullin avatar stevenaw avatar timc13 avatar villehakli avatar vinh84 avatar yorah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quartznet's Issues

Quartz job recovery periodically fails in clustered environment

Using Quartz 2.0.1 SqlSever with mirroring.

quartz.jobStore.type = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
quartz.jobStore.clustered = "true";
quartz.jobStore.lockHandler.type = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz";

Sometimes one sql server instance fails and I find in log error of this kind:

[ERROR] Quartz.Core.QuartzSchedulerThread - Runtime error occurred in main trigger firing loop.
System.ArgumentNullException: Connnection-transaction pair cannot be null
Parameter name: cth
at Quartz.Impl.AdoJobStore.JobStoreSupport.RollbackConnection(ConnectionAndTransactionHolder cth) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3300
at Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Func2 txCallback) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3463 at Quartz.Impl.AdoJobStore.JobStoreSupport.TriggersFired(IList1 triggers) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 2550
at Quartz.Core.QuartzSchedulerThread.Run() in c:\Work\OpenSource\quartznet\src\Quartz\Core\QuartzSchedulerThread.cs:line 369
DateTime=2012-09-18T19:27:29.0470000Z

After this message I assume job gets blocked and in logs with certain periodicity appears the following message:
Quartz.Impl.AdoJobStore.JobStoreTX - Handling 1 trigger(s) that missed their scheduled fire-time.

I suppose that this is an attempt to handle blocked job but for now I have to wait when job gets blocked and see the dump.
Other jobs (about 25) works as expected. By blocked I mean that job is not fired.

Blocked trigger has state ACQUIRED in table TRIGGERS . This trigger also appears in FIRED_TRIGGERS table with state ACQUIRED. Interestingly value of NEXT_FIRE_TIME field in TRIGGERS table for this trigger is constantly increasing although job is not called.

Service is stopping normally so I assume no job thread gets blocked in this scenario however restarting service does not help. All triggers start working normally beside blocked one.

Solution is to reset manually trigger's state to WAITING in TRIGGERS table.

Internalize C5 dependency

Quartz uses C5 as dependency and it can be sometimes hard to manage as we use older version to get .NET 3.5 support, users probably want to use newer version anyway.

Add simple mechanism to exchange underlying job storage

Currently it is pretty complicated to introduce your own persistence mechanism. For example if I want to use RavenDB to store the triggers and jobs I must re-implement almost the whole StdSchedulerFactory. Provide either guidance how to implement persistence on top of the current architecture or simplify the architecture.

Scheduler Shutdown Freezes when There are Jobs Still Running

I'm using the latest version from NuGet. I ran your examples in visual studio 2010 and I noticed that scheduler shutdown freezes and code after that is never called when there are still running jobs. Specifically see example 5 and change the last sleep from 10 minutes to 1 minute and shutdown(true) to false. My understanding is that when I set shutdown(false) it should terminate all jobs no matter if they're finished or not but instead I see this in log:

---group1.statefulJob2 executing.[Sun, 08 Jul 2012 10:19:15 GMT]
---group1.statefulJob1 executing.[Sun, 08 Jul 2012 10:19:15 GMT]
10:20:09:963 [INFO] Quartz.Examples.Example5.MisfireExample - ------- Shutting
Down ---------------------
10:20:17:056 [INFO] Quartz.Core.QuartzScheduler - Scheduler ExampleDefaultQuart
zScheduler_$NON_CLUSTERED shutting down.
10:20:17:059 [INFO] Quartz.Core.QuartzScheduler - Scheduler ExampleDefaultQuart
zScheduler
$_NON_CLUSTERED paused.

And it freezes there no matter how long I wait.

Implement 'processStreamAndScheduleJobs' method

When working with streams deleting triggers requires a bit of extra work. The pre-processing commands are not executed when only streams are being used. The behavior is a bit different than when working with files.

Current behavior can be worked around by inheriting the XMLSchedulingDataProcessor and calling the ExecutePreProcessingCommands method for inherited class explicitly.

It would be nice if I could just call a method directly for XMLSchedulingDataProcessor which would execute pre-processing command internally when working with streams.

Perhaps the 'processStreamAndScheduleJobs' method (or similar functionality), which exists in java source code, could be implemented to achieve the desired behavior.

Triggers fired milliseconds too early

I experienced triggers being fired 1 millisecond ahead of schedule.
In my application I create among others simple triggers that should fire once at specified time. I use TriggerBuilder.StartAt method to set the time. Method's documentation says:

the Trigger will NOT fire before this time, regardless of the Trigger's schedule

However, in the log files I sometimes see that task scheduled for 2012-11-28 07:12:24 runs at 2012-11-28 07:12:23,999. This clearly breaks the method's contract. And it breaks the application.
It is very hard to reproduce, it occurs only on one machine and not all the time.

I looked around Quartz code and I think that problem is caused by the following line in the QuartzSchedulerThread class:

while (timeUntilTrigger > TimeSpan.FromMilliseconds(2))

It seems that this implementation is fine with firing triggers 1 or 2 milliseconds before schedule. This is however not what the documentation/specification says.

DailyTimeIntervalTriggerImpl - Unused Constructor Parameters

Hi,

I'm seeing that not all the constructor parameters in DailyTimeIntervalTriggerImpl are being used. For example, notice the startTimeOfDayUtc & endTimeOfDayUtc parameters below:

public DailyTimeIntervalTriggerImpl(string name, String group, DateTimeOffset startTimeUtc,
                                            DateTimeOffset? endTimeUtc, TimeOfDay startTimeOfDayUtc, TimeOfDay endTimeOfDayUtc,
                                            IntervalUnit intervalUnit, int repeatInterval)
            : base(name, group)
        {
            StartTimeUtc = startTimeUtc;
            EndTimeUtc = endTimeUtc;
            RepeatIntervalUnit = intervalUnit;
            RepeatInterval = repeatInterval;
        }

Maybe I'm just missing something, because Quartz (java) is similar in this respect. Thoughts?

Thanks,
-Mihai

Question: C5.dll is not latest

Hello,

Since C5 is internalized, won't it be good if C5 is updated to the latest version (1.1.1.0)?

I am happy to see that C5.dll is not in bin\4.0\release\Quartz, but when I build using visual studio 2010 in release mode, I found that the C5.dll is in the build\4.0\Release\Quartz folder. I thought it has been internalized.

Is there anyway I can internalize the C5.dll myself if I update the C5.dll in Quartz.2010.sln to the latest version?

Thank you.

DailyTimeIntervalTriggerImpl Validate broken

if (repeatIntervalUnit != IntervalUnit.Second && repeatIntervalUnit != IntervalUnit.Minute && repeatIntervalUnit == IntervalUnit.Hour)
{
throw new SchedulerException("Invalid repeat IntervalUnit (must be Second, Minute or Hour).");
}

obvisously should be

if (repeatIntervalUnit != IntervalUnit.Second && repeatIntervalUnit != IntervalUnit.Minute && repeatIntervalUnit != IntervalUnit.Hour)
{
throw new SchedulerException("Invalid repeat IntervalUnit (must be Second, Minute or Hour).");
}

A small but devastating error :). Might be a good idea to include a test of validate in tests.

Support for Oracle ODP 11.2 Release 4

The current scheduler only supports Oracle Client version 2.102.2.20 (oracle.dataAccess.Client).

With the latest release of oracle 11g, support of the latest client needs to be added

Daily trigger doesn't behave as expected

I have code to configure a trigger as such:

var trigger = TriggerBuilder.Create()
.WithIdentity("Trigger for: " + job.Name)
.WithSchedule(DailyTimeIntervalScheduleBuilder.Create()
.OnEveryDay()
.StartingDailyAt(new TimeOfDay(nextTime.Hour, nextTime.Minute))
.Build();

Expected:
Every day at nextTime.Hour : nextTime.Minute the job is created and run 1 time

Actual:
Job runs immediately, and it repeats every single minute.

It seems as if StartingDailyAt() would prevent immediate execution, and should prevent minutely re-runs. It's also really unclear, given the lack of documentation, how to get my expected behavior. Do I call WithRepeatCount(0)? Will this prevent minutely repeating? Will this prevent daily repeating?

API not matching documentation

Hi, I'm new to Quartz. It came highly recommend from around the web so I thought I'd give it a go.

But as a newcomer to this API I find it hard to use the fine tutorials on the main site (http://quartznet.sourceforge.net/tutorial/) because they don't work.

I'm a bit puzzled as to why the refactor of JobDetail to JobDetailImpl was done. I wasn't in the slightest in doubt that JobDetail was the concrete implementation of IJobDetail. As goes for all the others.

Also there seem to be missing functions in the TriggerUtils class.
I only have:

  • ComputeEndTimeToAllowParticularNumberOfFirings
  • ComputeFireTimes
  • ComputeFireTimesBetween

But the tutorial uses stuff like:
Trigger trigger = TriggerUtils.MakeHourlyTrigger();

To make things worse Trigger doesn't even exists nor does TriggerImpl.

Please make this user friendly, again - it would seem :(

JobStoreCMT does not open non managed connections.

JobStoreCMT does not call Open on nonmanaged database connections it creates. In result, when scheduler starts and tries to recover jobs, the following exception is thrown:

System.InvalidOperationException: ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.

Metod JobStoreCMT.GetNonManagedTXConnection should call conn.Open before returning the connection.

InstanceID = "AUTO" may cause "String or binary data would be truncated" error on qrtz_fired_triggers.entry_id

I've been testing Quartz.net in a clustered environment with instanceId set to AUTO. With this setting the instance names are quite long, for example:

webrole1.cba40774e2b446b997629b1099715a5e.mywebfarm.3177451923.europewest.internal.cloudapp.net634909018685635601

This has caused problems in the InsertFiredTrigger-method of the StdAdoDelegate:

Quartz.JobPersistenceException: Couldn't acquire next trigger: String or binary data would be truncated.
The statement has been terminated. ---> System.Data.SqlClient.SqlException: String or binary data would be truncated.
The statement has been terminated.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Quartz.Impl.AdoJobStore.StdAdoDelegate.InsertFiredTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, String state, IJobDetail job)
at Quartz.Impl.AdoJobStore.JobStoreSupport.AcquireNextTrigger(ConnectionAndTransactionHolder conn, DateTimeOffset noLaterThan, Int32 maxCount, TimeSpan timeWindow)

This seems to be caused by the entry_id field in qrtz_fired_triggers table.

I was able to get around this by making the field larger:

alter table qrtz_fired_triggers alter column entry_id nvarchar(200) not null

But I wonder if this is the best solution?

SimpleThreadPool should not prevent a process from terminating

Currently SimpleThreadPool uses foreground threads. It should instead set the IsBackground property of all the threads it creates to true, so if the scheduler isn't properly shut down, the threads created by SimpleThreadPool will not be the sole reason to keep the process alive. This means that in a GUI-based application, closing its main window actually leaves the process running (barring proper scheduler shutdown), which may go unnoticed.

Add method to IJobFactory to destroy a job instance created by the factory

On the assumption that each job execution gets a new job instance from the factory, Quartz should ask the IJobFactory to destroy the instance when the job execution is finished.

The main reason for this is that there may be special logic to tear down the instance created by the factory. In my case, I have a Unity container that creates a dependency hierarchy for a job that has IDisposable types. The only thing that knows how to destroy the dependency hierarchy correctly is the unity container. The implementation of IJobFactory however does not have the facility for the container to be told to destroy the job instance.

Scheduler.TriggerJob(JobKey, JobDataMap) ignores JobDataMap

What it says on the tin.

Futher details

Assembly version from NuGet: 2.0.1.100

When calling IJobExecutionContext.Scheduler.TriggerJob(JobKey, JobDataMap) the actual JobDataMap received in the context of the triggered job is defined only by the job's respective JobDetail, including if the JobDetail never defines a JobDataMap. This is contrary to the Quatz documentation (http://quartz-scheduler.org/api/2.1.0/org/quartz/JobDataMap.html) which states that the passed JobDataMap should be a merged version of both the Trigger's JobDataMap and the JobDetail's JobDataMap.

DailyTimeIntervalTriggerPersistenceDelegate does not handle empty time interval properly

Hi,

I've been doing some small test applications with Quartz.NET, and I'm getting the following exception when starting the Scheduler:

Quartz.SchedulerConfigException was unhandled
HResult=-2146233088
Message=Failure occured during job recovery.
Source=Quartz
StackTrace:
at Quartz.Impl.AdoJobStore.JobStoreSupport.SchedulerStarted() in c:\Work\OpenSource\Quartz.NET\quartznet\src

\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 543
at Quartz.Core.QuartzScheduler.Start() in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Core

\QuartzScheduler.cs:line 442
at Quartz.Impl.StdScheduler.Start() in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl

\StdScheduler.cs:line 222
at QuartzDemo.Scheduler.CreateJobIfNotPersisted() in c:\Users\Sagostinho\Desktop\QuartzDemo\QuartzDemo

\Scheduler.cs:line 40
at QuartzDemo.Scheduler.Main(String[] args) in c:\Users\Sagostinho\Desktop\QuartzDemo\QuartzDemo

\Scheduler.cs:line 17
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback,

Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object

state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object

state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: Quartz.JobPersistenceException
HResult=-2146233088
Message=Couldn't retrieve trigger: Input string was not in a correct format.
Source=Quartz
StackTrace:
at Quartz.Impl.AdoJobStore.JobStoreSupport.RetrieveTrigger(ConnectionAndTransactionHolder conn, TriggerKey

triggerKey) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 1319
at Quartz.Impl.AdoJobStore.JobStoreSupport.RecoverMisfiredJobs(ConnectionAndTransactionHolder conn, Boolean

recovering) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 750
at Quartz.Impl.AdoJobStore.JobStoreSupport.RecoverJobs(ConnectionAndTransactionHolder conn) in c:\Work

\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 701
at Quartz.Impl.AdoJobStore.JobStoreSupport.b__2(ConnectionAndTransactionHolder conn) in c:

\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 643
at Quartz.Impl.AdoJobStore.JobStoreSupport.<>c__DisplayClass74.b__73

(ConnectionAndTransactionHolder conn) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore

\JobStoreSupport.cs:line 3362
at Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Func`2 txCallback) in

c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3414
at Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Action`1 txCallback)

in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3362
at Quartz.Impl.AdoJobStore.JobStoreSupport.RecoverJobs() in c:\Work\OpenSource\Quartz.NET\quartznet\src

\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 643
at Quartz.Impl.AdoJobStore.JobStoreSupport.SchedulerStarted() in c:\Work\OpenSource\Quartz.NET\quartznet

\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 539
InnerException: System.FormatException
HResult=-2146233033
Message=Input string was not in a correct format.
Source=mscorlib
StackTrace:
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number,

NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.Int32.Parse(String s)
at Quartz.Impl.AdoJobStore.DailyTimeIntervalTriggerPersistenceDelegate.GetTriggerPropertyBundle

(SimplePropertiesTriggerProperties props) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore

\DailyTimeIntervalTriggerPersistenceDelegate.cs:line 151
at

Quartz.Impl.AdoJobStore.SimplePropertiesTriggerPersistenceDelegateSupport.LoadExtendedTriggerProperties

(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl

\AdoJobStore\SimplePropertiesTriggerPersistenceDelegateSupport.cs:line 176
at Quartz.Impl.AdoJobStore.StdAdoDelegate.SelectTrigger(ConnectionAndTransactionHolder conn, TriggerKey

triggerKey) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\StdAdoDelegate.cs:line 1510
at Quartz.Impl.AdoJobStore.JobStoreSupport.RetrieveTrigger(ConnectionAndTransactionHolder conn,

TriggerKey triggerKey) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line

1314
InnerException:

As shown in the stack trace, I'm using the AdoJobStore with an SQL Server 2008 database.
Looking at the source code, the exception happens while parsing a date (comma separated) in the DailyTimeIntervalTriggerPersistenceDelegate:

            TimeOfDay endTimeOfDay;
            if (nums.Length >= 6)
            {
                int hour = Int32.Parse(nums[3]);
                int min = Int32.Parse(nums[4]);
                int sec = Int32.Parse(nums[5]);
                endTimeOfDay = new TimeOfDay(hour, min, sec);
            }

Looking at the database, it seems the fault is in a row of the QRTZ_SIMPROP_TRIGGERS table which contains the "0,0,0,,,," value in the STR_PROP_3 column.

Quartz SendEmailJob need to use using pattern on smtpclient

Smtpclient implements IDisposable.
It is a best practice to use the using pattern to make sure that smtpclient will
clean up it's own resource when go out of scope from the using-block.
The using pattern will clean up even after exceptions are thrown inside.

PlugInExample doesn't execute any jobs

PlugInExample still reports 0 jobs executed despite the recent changes by commit 186e3e2.

19:00:01:959 [INFO]  Quartz.Impl.StdSchedulerFactory - Using default implementation for object serializer
19:00:01:990 [INFO]  Quartz.Impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
19:00:02:094 [INFO]  Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: Quartz.Core.SchedulerS
ignalerImpl
19:00:02:095 [INFO]  Quartz.Core.QuartzScheduler - Quartz Scheduler v.2.1.0.400 created.
19:00:02:099 [INFO]  Quartz.Simpl.RAMJobStore - RAMJobStore initialized.
19:00:02:150 [INFO]  Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.1.0.400) 'ExampleDefaultQua
rtzScheduler' 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.SimpleThreadPool' - with 10 threads.
  Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistence. and is not clustered.

19:00:02:151 [INFO]  Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'ExampleDefaultQuartzScheduler' initialized
19:00:02:151 [INFO]  Quartz.Impl.StdSchedulerFactory - Quartz scheduler version: 2.1.0.400
19:00:02:153 [INFO]  Quartz.Examples.Example10.PlugInExample - ------- Initialization Complete -----------
19:00:02:153 [INFO]  Quartz.Examples.Example10.PlugInExample - ------- Not Scheduling any Jobs - relying on XML definiti
ons --
19:00:02:153 [INFO]  Quartz.Examples.Example10.PlugInExample - ------- Starting Scheduler ----------------
19:00:02:159 [INFO]  Quartz.Core.QuartzScheduler - Scheduler ExampleDefaultQuartzScheduler_$_NON_CLUSTERED started.
19:00:02:160 [INFO]  Quartz.Examples.Example10.PlugInExample - ------- Started Scheduler -----------------
19:00:02:161 [INFO]  Quartz.Examples.Example10.PlugInExample - ------- Waiting five minutes... -----------
19:05:02:144 [INFO]  Quartz.Examples.Example10.PlugInExample - ------- Shutting Down ---------------------
19:05:02:155 [INFO]  Quartz.Core.QuartzScheduler - Scheduler ExampleDefaultQuartzScheduler_$_NON_CLUSTERED shutting down
.
19:05:02:160 [INFO]  Quartz.Core.QuartzScheduler - Scheduler ExampleDefaultQuartzScheduler_$_NON_CLUSTERED paused.
19:05:02:611 [INFO]  Quartz.Core.QuartzScheduler - Scheduler ExampleDefaultQuartzScheduler_$_NON_CLUSTERED Shutdown comp
lete.
19:05:02:612 [INFO]  Quartz.Examples.Example10.PlugInExample - ------- Shutdown Complete -----------------
19:05:02:615 [INFO]  Quartz.Examples.Example10.PlugInExample - Executed 0 jobs.
Example run successfully.

The equivalent example in Java includes a quartz.properties file in example10 like this:

org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin

org.quartz.plugin.jobInitializer.class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames: quartz_data.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound: true
org.quartz.plugin.jobInitializer.scanInterval: 120
org.quartz.plugin.jobInitializer.wrapInUserTransaction: false

XMLSchedulingDataProcessorPlugin incompatible with StdAdoDelegate when useProperties=true

I'm playing around with Quartz.net and adding support for a persistent job store via the ADO.NET Job Store. As per the recommendation in tutorial 9, I'm instructing the job store to persist job parameters in plain text rather than BLOBs, using the configuration:

Unfortunately in triggering a simple job, which has no explicit job data map, I receive this error:

JobDataMap values must be Strings when the 'useProperties' property is set. Key of offending value: LAST_MODIFIED_TIME

When looking in the debugger at the JobDataMap object provided to the job I scheduled, there is no LAST_MODIFIED_TIME present. Digging a bit deeper, it seems that there is another job running called FileScanJob, scheduled by the XMLSchedulingDataProcessorPlugin (used to read the job and trigger configuration from an XML file). This job adds the LAST_MODIFIED_TIME entry to its JobDataMap during job execution, which is of type DateTime rather than string.

This raising an exception due to the implementation of the StdAdoDelegate class. When the quartz.jobStore.useProperties configuration value is set to true it will deliberately fail to write to the job store database any job data that does not use string for both key and value. Despite this restriction, it still uses binary serialization to store the data after this check (in the form of a NameValueCollection).

To come back to the original reason for setting this property, the tutorial advises to use it to avoid serializing complex types and getting into versioning issues after type upgrades. I'd contest that this objective could be simply achieved by supporting all the primitive .NET types whose serialization is not likely to change. The change to StdAdoDelegate would be to perform a type validation of each name/value pair to ensure only simple types are in use in the case of quartz.jobStore.useProperties being true and convert it to System.Collections.Hashtable to allow for changes to the JobDataMap class to be made in Quartz without causing serialization issues.

Another solution could be to have an XmlAdoDelegate that used XML serialization instead of binary serialization.

Maybe I am missing some extra design constraint here?

PreserveHourOfDayAcrossDaylightSavings of CalendarIntervalTriggerImpl is not working properly.

I could be wrong, I am only checking the results of using the TriggerUtils.ComputeFireTimes utility method. But I noticed that it is not preserving the hour across daylight savings time for me.

I am guessing that this happens because when adjustments are being made to the sTime variable in the GetFireTimeAfter(DateTimeOffset? afterTime, bool ignoreEndTime) method right before we check using the DaylightSavingHourShiftOccuredAndAdvanceNeeded(ref DateTimeOffset newTime, int initialHourOfDay) function. I think we need to convert to the target timezone once again to check to see if the hour has actually changed or not.

So here are my changes to that method that seems to work well.

        private bool DaylightSavingHourShiftOccuredAndAdvanceNeeded(ref DateTimeOffset newTime, int initialHourOfDay)
        {
            //need to apply timezone again to properly check if initialHourOfDay has changed.
            DateTimeOffset toCheck = TimeZoneInfo.ConvertTime(newTime, this.TimeZone);

            if (PreserveHourOfDayAcrossDaylightSavings && toCheck.Hour != initialHourOfDay)
            {
                newTime = new DateTimeOffset(newTime.Year, newTime.Month, newTime.Day, initialHourOfDay, newTime.Minute, newTime.Second, newTime.Millisecond, toCheck.Offset);
                if (newTime.Hour != initialHourOfDay)
                {
                    return true;
                }
            }
            return false;
        }

CheckNotZombied causes underlying connection open exception to be discarded

When using a quartz.dataSource.quartzDataSource.provider=SqlServerCe-400 and the underlying database file (the .sdf file) is marked readonly the Quartz.Impl.AdoJobStore.JobStoreSupport.GetConnection() fails with an exception on conn.Open(). This is only one example of many possible exceptions (file not found, other permissions, etc etc).

The underlying Exception is rethrown as a JobPersistenceException (Failed to obtain DB connection from data source). This is caught in ExecuteInNonManagedTXLock which then does a RollbackConnection which passes the null conn to CheckNotZombied... which throws a new ArgumentNullException.

So... long story short... any connection exceptions are always eaten.

Not sure what the best fix would be. CheckNotZombied is only called from RollbackConnection and CommitConnection... whilst RollbackConnection is called from half a dozen places.

However... it is concerning that an exception handler is doing "lots of work" but the "lots of work" isn't exception safe.

Sporadic JobPersistenceException (SerializationException)

From time to time our application crashes when it retrieves a list of jobs from Quartz.net while a job is executing.

Quartz.JobPersistenceException: Couldn't retrieve job: End of Stream encountered before parsing was completed. ---> System.Runtime.Serialization.SerializationException: End of Stream encountered before parsing was completed.
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at Quartz.Impl.AdoJobStore.StdAdoDelegate.GetObjectFromBlob(IDataReader rs, Int32 colIndex)
at Quartz.Impl.AdoJobStore.StdAdoDelegate.SelectJobDetail(ConnectionAndTransactionHolder conn, JobKey jobKey, ITypeLoadHelper loadHelper)
at Quartz.Impl.AdoJobStore.JobStoreSupport.RetrieveJob(ConnectionAndTransactionHolder conn, JobKey jobKey)
--- End of inner exception stack trace ---
at Quartz.Impl.AdoJobStore.JobStoreSupport.RetrieveJob(ConnectionAndTransactionHolder conn, JobKey jobKey)
at Quartz.Impl.AdoJobStore.JobStoreSupport.<>c__DisplayClass19.b__18(ConnectionAndTransactionHolder conn)
at Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Func2 txCallback) at Quartz.Impl.AdoJobStore.JobStoreTX.ExecuteInLock(String lockName, Func2 txCallback)
at Quartz.Impl.AdoJobStore.JobStoreSupport.RetrieveJob(JobKey jobKey)
at Quartz.Core.QuartzScheduler.GetJobDetail(JobKey jobKey)
at Quartz.Impl.StdScheduler.GetJobDetail(JobKey jobKey)
...

We are using Sql Server Compact 4.0 (provider SqlServerCe-400) with the AdoJobStore.JobStoreTX.
While trying to fix this problem, I set the lockHandler to UpdateLockRowSemaphore and the driverDelegateType to StdAdoDelegate, with no effect.

When I set the Mode in the connection string to Exclusive, the application crashes after a short time with a sharing violation although there is no other application accessing the database file.

Maybe a separate driver delegate for Sql Server Compact is needed to keep the connection, so that the Mode can be set to Exclusive?
Or is this a multithreading problem?

packages.config not included in projects

I've noticed that the packages.config files are not included in the .csproj project files.

Is there a special reason for that? If not, I think it's more consistent if those files are included in the .csproj. Visual Studio's wizards will do that by default when creating a new project, so it's generally expected practice.

Scheduled Shutdown blocked even if waitForJobsToComplete is false

Possibly related to #67Quartz job recovery periodically fails in clustered environment , we are finding that the scheduler blocks indefinitely when requested to shutdown by the hosting service in QuartzScheduler.Shutdown(bool) in the following thread Join operation, despite waitForJobsToComplete being false and all worker threads previously reported as shutdown:

// Scheduler thread may have be waiting for the fire time of an acquired // trigger and need time to release the trigger once halted, so make sure // the thread is dead before continuing to shutdown the job store. try {
schedThread.Join();

} catch (ThreadInterruptedException) { }

The Windows service control manager then reports the service as refusing to shutdown.

The error presumably leading to the deadlock situation occurs intermittently when a CRON trigger fires

2012-10-25 07:00:00.277 Error while executing the Runnable:QuartzServer_Worker-8 |  | System.ArgumentNullException System.ArgumentNullException: Connnection-transaction pair cannot be null
Parameter name: cth
   at Quartz.Impl.AdoJobStore.JobStoreSupport.RollbackConnection(ConnectionAndTransactionHolder cth) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3300
   at Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Func`2 txCallback) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3463
   at Quartz.Core.JobRunShell.Run() in c:\Work\OpenSource\quartznet\src\Quartz\Core\JobRunShell.cs:line 281

I understand that #67 is currently being addressed, but irrespectively, is an indefinite Join the appropriate course of action here for what should be a non-waiting shutdown?

Oracle does not support Boolean Datatype for columns

The new version of Quartz.net considers that all databases can have columns with Boolean DataType. However incase of oracle the GetBooleanDBValue() function fails as oracle does not support Boolean type columns.

This would require fix to the code so that if the Provider is Oracle we need to use " 1 or 0" values instead of "true/false".

We are facing issues due to this and would request you to please take this up on priority.

Thanks,
Kshitiz Pandey

Quartz job periodically fails in clustered environment with "Transaction not connected, or was disconnected" exception

We upgraded yesterday. Unfortunately issue is not fixed. We still see "Transaction not connected, or was disconnected" exception.

Environment:
We are using SQL Server 2012 running in Windows Azure Virtual Machine.

Configuration:

            properties["quartz.scheduler.instanceName"]                 = "default";
            properties["quartz.scheduler.instanceId"]                   = "AUTO";
            properties["quartz.threadPool.type"]                        = "Quartz.Simpl.SimpleThreadPool, Quartz";
            properties["quartz.threadPool.threadCount"]                 = "10";
            properties["quartz.threadPool.threadPriority"]              = "Normal";
            properties["quartz.jobStore.type"]                          = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
            properties["quartz.jobStore.tablePrefix"]                   = "QRTZ_";
            properties["quartz.jobStore.clustered"]                     = "true";
            properties["quartz.jobStore.driverDelegateType"]            = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";
            properties["quartz.jobStore.dataSource"]                    = "default";
            properties["quartz.jobStore.useProperties"]                 = "true";
            properties["quartz.dataSource.default.provider"]            = "SqlServer-20";
            properties["quartz.dataSource.default.connectionString"]    = connectionString;

            this.Scheduler = new StdSchedulerFactory(properties).GetScheduler();

Exception:

2013-01-04 18:13:34,933 [default_QuartzSchedulerThread] ERROR Quartz.Impl.AdoJobStore.JobStoreTX - Couldn't rollback ADO.NET connection. Transaction not connected, or was disconnected

System.Data.DataException: Transaction not connected, or was disconnected
at Quartz.Impl.AdoJobStore.JobStoreSupport.RollbackConnection(ConnectionAndTransactionHolder cth) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3251
2013-01-04 18:13:34,933 [default_QuartzSchedulerThread] ERROR Quartz.Core.ErrorLogger - An error occurred while scanning for the next trigger to fire.

Quartz.JobPersistenceException: Couldn't acquire next trigger: Transaction (Process ID 53) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. ---> System.Data.SqlClient.SqlException: Transaction (Process ID 53) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows) at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more) at System.Data.SqlClient.SqlDataReader.Read() at Quartz.Impl.AdoJobStore.StdAdoDelegate.SelectTriggerToAcquire(ConnectionAndTransactionHolder conn, DateTimeOffset noLaterThan, DateTimeOffset noEarlierThan, Int32 maxCount) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\StdAdoDelegate.cs:line 2099 at Quartz.Impl.AdoJobStore.JobStoreSupport.AcquireNextTrigger(ConnectionAndTransactionHolder conn, DateTimeOffset noLaterThan, Int32 maxCount, TimeSpan timeWindow) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 2383 --- End of inner exception stack trace --- at Quartz.Impl.AdoJobStore.JobStoreSupport.AcquireNextTrigger(ConnectionAndTransactionHolder conn, DateTimeOffset noLaterThan, Int32 maxCount, TimeSpan timeWindow) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 2462 at Quartz.Impl.AdoJobStore.JobStoreSupport.<>c__DisplayClass65.<AcquireNextTriggers>b__62(ConnectionAndTransactionHolder conn) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 2354 at Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Func2 txCallback) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3432
at Quartz.Impl.AdoJobStore.JobStoreSupport.AcquireNextTriggers(DateTimeOffset noLaterThan, Int32 maxCount, TimeSpan timeWindow) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 2352
at Quartz.Core.QuartzSchedulerThread.Run() in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Core\QuartzSchedulerThread.cs:line 277 [See nested exception: System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 53) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
at System.Data.SqlClient.SqlDataReader.Read()
at Quartz.Impl.AdoJobStore.StdAdoDelegate.SelectTriggerToAcquire(ConnectionAndTransactionHolder conn, DateTimeOffset noLaterThan, DateTimeOffset noEarlierThan, Int32 maxCount) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\StdAdoDelegate.cs:line 2099
at Quartz.Impl.AdoJobStore.JobStoreSupport.AcquireNextTrigger(ConnectionAndTransactionHolder conn, DateTimeOffset noLaterThan, Int32 maxCount, TimeSpan timeWindow) in c:\Work\OpenSource\Quartz.NET\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 2383
ClientConnectionId:1323bab5-d482-456e-98db-32859cc353d3]

Trace throwing exception

Line 924 'log.InfoFormat("Deleting all jobs in group: {}", group);' in XMLSchedulingDataProcessor.cs.

Its missing a 0 placeholder between {}

Add support for custom database schema in addition to table prefix

I want to push the Quartz database SQL Server schema changes into its own schema. This will allow me to separate the Quartz part of the database from my own application. It looks like I can apply a workaround to make this happen by either:

a) Putting the custom schema name in the table prefix
b) Use table alias's

It would be great if there was formal support for this though.

Improve error reporting for database connection failure

Hi,

I'm using Quartz.NET 2.0.1 with SQL Server store. The error reporting for database connection failure is very confusing.

For example, if the connection string is incorrect, Quartz.net will throw a "Connnection-transaction pair cannot be null" exception at Quartz.Impl.AdoJobStore.JobStoreSupport.RollbackConnection(ConnectionAndTransactionHolder cth).

This exception makes it very hard to find the real cause. I had been debugging for 2 hours before I found that this was just because of database connection failure. :(

I checked the source code: https://github.com/quartznet/quartznet/blob/master/src/Quartz/Impl/AdoJobStore/JobStoreSupport.cs#L3468

When Quartz fails to obtain database connection in ExecuteInNonManagedTXLock method (JobStoreSupport, line 3452), a JobPersistenceException is thrown from ExecuteInNonManagedTXLock method. Then this exception is caught in line 3468. At this time, the "conn" is null, so RollbackConnection(conn) will throw "Connnection-transaction pair cannot be null" exception. So, I think we need to first check if "conn" is null in line 3468?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.