Permalink
Please sign in to comment.
Showing
with
2,733 additions
and 0 deletions.
- +22 −0 .gitattributes
- +2 −0 .gitignore
- +1 −0 CNAME
- +304 −0 FAQ.md
- +2 −0 Gemfile
- +22 −0 _config.yml
- +168 −0 _layouts/default.html
- +11 −0 _layouts/redirect.html
- +17 −0 download.md
- +54 −0 features.md
- +14 −0 index.md
- +11 −0 license.md
- +35 −0 mailing-list.md
- +5 −0 mailing_list.md
- +111 −0 migration-guide.md
- +232 −0 stylesheets/default.css
- +33 −0 stylesheets/pygments.css
- +611 −0 stylesheets/site.css
- +23 −0 tutorial/advanced-enterprise-features.md
- +68 −0 tutorial/configuration-resource-usage-and-scheduler-factory.md
- +99 −0 tutorial/crontriggers.md
- +22 −0 tutorial/index.md
- +118 −0 tutorial/job-stores.md
- +66 −0 tutorial/jobs-and-triggers.md
- +5 −0 tutorial/lesson_1.md
- +5 −0 tutorial/lesson_10.md
- +5 −0 tutorial/lesson_11.md
- +5 −0 tutorial/lesson_12.md
- +5 −0 tutorial/lesson_2.md
- +5 −0 tutorial/lesson_3.md
- +5 −0 tutorial/lesson_4.md
- +5 −0 tutorial/lesson_5.md
- +5 −0 tutorial/lesson_6.md
- +5 −0 tutorial/lesson_7.md
- +5 −0 tutorial/lesson_8.md
- +5 −0 tutorial/lesson_9.md
- +31 −0 tutorial/miscellaneous-features.md
- +183 −0 tutorial/more-about-jobs.md
- +141 −0 tutorial/more-about-triggers.md
- +41 −0 tutorial/scheduler-listeners.md
- +118 −0 tutorial/simpletriggers.md
- +70 −0 tutorial/trigger-and-job-listeners.md
- +38 −0 tutorial/using-quartz.md
@@ -0,0 +1,22 @@ | ||
+# Auto detect text files and perform LF normalization | ||
+* text=auto | ||
+ | ||
+# Custom for Visual Studio | ||
+*.cs diff=csharp | ||
+*.sln merge=union | ||
+*.csproj merge=union | ||
+*.vbproj merge=union | ||
+*.fsproj merge=union | ||
+*.dbproj merge=union | ||
+ | ||
+# Standard to msysgit | ||
+*.doc diff=astextplain | ||
+*.DOC diff=astextplain | ||
+*.docx diff=astextplain | ||
+*.DOCX diff=astextplain | ||
+*.dot diff=astextplain | ||
+*.DOT diff=astextplain | ||
+*.pdf diff=astextplain | ||
+*.PDF diff=astextplain | ||
+*.rtf diff=astextplain | ||
+*.RTF diff=astextplain |
@@ -0,0 +1,2 @@ | ||
+/_site | ||
+/*.lock |
@@ -0,0 +1,304 @@ | ||
+--- | ||
+layout: default | ||
+title: Frequently Asked Questions | ||
+--- | ||
+ | ||
+*This FAQ was adapted from Quartz Java* | ||
+ | ||
+# General Questions | ||
+ | ||
+## What is Quartz | ||
+ | ||
+Quartz is a job scheduling system that can be integrated with, or used along | ||
+side virtually any other software system. The term "job scheduler" seems to | ||
+conjure different ideas for different people. As you read this tutorial, you | ||
+should be able to get a firm idea of what we mean when we use this term, but | ||
+in short, a job scheduler is a system that is responsible for executing | ||
+(or notifying) other software components when a pre-determined (scheduled) | ||
+time arrives. | ||
+ | ||
+Quartz is quite flexible, and contains multiple usage paradigms that can be | ||
+used separately or together, in order to achieve your desired behavior, and | ||
+enable you to write your code in the manner that seems most 'natural' to | ||
+your project. | ||
+ | ||
+Quartz is very light-weight, and requires very little setup/configuration - | ||
+it can actually be used 'out-of-the-box' if your needs are relatively basic. | ||
+ | ||
+Quartz is fault-tolerant, and can persist ('remember') your scheduled | ||
+jobs between system restarts. | ||
+ | ||
+Although Quartz is extremely useful for simply running certain system | ||
+processes on given schedules, the full potential of Quartz can be realized | ||
+when you learn how to use it to drive the flow of your application's | ||
+business processes. | ||
+ | ||
+## What is Quartz - From a Software Component View? | ||
+ | ||
+Quartz is distributed as a small dynamically linked library (.dll file) | ||
+that contains all of the core Quartz functionality. The main interface (API) to this | ||
+functionality is the Scheduler interface. It provides simple operations | ||
+such as scheduling/unscheduling jobs, starting/stopping/pausing the scheduler. | ||
+ | ||
+If you wish to schedule your own software components for execution they must | ||
+implement the simple Job interface, which contains the method execute(). | ||
+If you wish to have components notified when a scheduled fire-time arrives, | ||
+then the components should implement either the TriggerListener or JobListener | ||
+interface. | ||
+ | ||
+The main Quartz 'process' can be started and ran within your own application, | ||
+or a stand-alone application (with an remote interface). | ||
+ | ||
+# Why not just use System.Timers.Timer? | ||
+ | ||
+.NET Framework has "built-in" timer capabilities, through the | ||
+System.Timers.Timer class - why would someone use Quartz rather than these | ||
+standard features? | ||
+ | ||
+There are many reasons! Here are a few: | ||
+ | ||
+* Timers have no persistence mechanism. | ||
+* Timers have inflexible scheduling (only able to set start-time & repeat interval, nothing based on dates, time of day, etc. | ||
+* Timers don't utilize a thread-pool (one thread per timer) | ||
+* Timers have no real management schemes - you'd have to write your own mechanism for being able to remember, organize and retreive your tasks by name, etc. | ||
+ | ||
+...of course to some simple applications these features may not be important, | ||
+in which case it may then be the right decision not to use Quartz.NET. | ||
+ | ||
+## How do I build the Quartz source? | ||
+ | ||
+Although Quartz ships "pre-built" many people like to make their own | ||
+alterations and/or build the latest 'non-released' version of Quartz from | ||
+Subversion. To do this, follow the instructions in the "README.TXT" file | ||
+that ships with Quartz. | ||
+ | ||
+# Miscellaneous Questions</title> | ||
+ | ||
+## How many jobs is Quartz capable of running? | ||
+ | ||
+This is a tough question to answer... the answer is basically "it depends". | ||
+ | ||
+I know you hate that answer, to here's some information about what it depends "on". | ||
+ | ||
+First off, the JobStore that you use plays a significant factor. | ||
+The RAM-based JobStore is MUCH (1000x) faster than the ADO.NET-based JobStore. | ||
+The speed of AdoJobStore depends almost entirely on the speed of the | ||
+connection to your database, which data base system that you use, and what | ||
+hardware the database is running on. Quartz actually does very little | ||
+processing itself, nearly all of the time is spent in the database. Of course | ||
+RAMJobStore has a more finite limit on how many Jobs & Triggers can be stored, | ||
+as you're sure to have less RAM than hard-drive space for a database. | ||
+You may also look at the FAQ "How do I improve the performance of AdoJobStore?" | ||
+ | ||
+So, the limitting factor of the number of Triggers and Jobs Quartz can "store" | ||
+and monitor is really the amount of storage space available to the JobStore | ||
+(either the amount of RAM or the amount of disk space). | ||
+ | ||
+Now, aside from "how many can I store?" is the question of "how many jobs | ||
+can Quartz be running at the same moment in time?" | ||
+ | ||
+One thing that CAN slow down quartz itself is using a lot of listeners | ||
+(TriggerListeners, JobListeners, and SchedulerListeners). The time spent in | ||
+each listener obviously adds into the time spent "processing" a job's | ||
+execution, outside of actual execution of the job. This doesn't mean that | ||
+you should be terrified of using listeners, it just means that you should | ||
+use them judiciously - don't create a bunch of "global" listeners if you can | ||
+really make more specialized ones. Also don't do "expensive" things in the | ||
+listeners, unless you really need to. Also be mindful that many | ||
+plug-ins (such as the "history" plugin) are actually listeners. | ||
+ | ||
+The actual number of jobs that can be running at any moment in time is | ||
+limitted by the size of the thread pool. If there are five threads in | ||
+the pool, no more than five jobs can run at a time. Be careful of making a | ||
+lot of threads though, as the VM, Operating System, and CPU all have a hard | ||
+time juggling lots of threads, and performance degrades just because of all | ||
+of the management. In most cases performance starts to tank as you get into | ||
+the hundreds of threads. Be mindful that if you're running within an | ||
+application server, it probably has created at least a few dozen threads | ||
+of its own! | ||
+ | ||
+Aside from those factors, it really comes down to what your jobs DO. | ||
+If your jobs take a long time to complete their work, and/or their work is | ||
+very CPU-intensive, then you're obviously not going to be able to run very | ||
+many jobs at once, nor very many in a given spanse of time. | ||
+ | ||
+Finally, if you just can't get enough horse-power out of one Quartz instance, | ||
+you can always load-balance many Quartz instances (on separate machines). | ||
+Each will run the jobs out of the shared database on a first-come first-serve | ||
+basis, as quickly as the triggers need fired. | ||
+ | ||
+So here you are this far into the answer of "how many", and I still | ||
+haven't given you a number And I really hate to, because of all of the | ||
+variables mentioned above. So let me just say, there are installments of | ||
+Quartz Java out there that are managing hundreds-of-thousands of Jobs and Triggers, | ||
+and that at any given moment in time are executing dozens of jobs - and this | ||
+excludes using load-balancing. With this in mind, most people should feel | ||
+confident that they can get the performance out of Quartz that they need. | ||
+ | ||
+# Questions About Jobs | ||
+ | ||
+## How can I control the instantiation of Jobs?</title> | ||
+ | ||
+See Quartz.Spi.IJobFactory and the Quartz.IScheduler.JobFactory property. | ||
+ | ||
+## How do I keep a Job from being removed after it completes?</title> | ||
+ | ||
+Set the property JobDetail.Durable = true - which instructs Quartz not to | ||
+delete the Job when it becomes an "orphan" (when the Job not longer has a | ||
+Trigger referencing it). | ||
+ | ||
+## How do I keep a Job from firing concurrently? | ||
+ | ||
+Make the job class implement IStatefulJob rather than Job. Read the API | ||
+documentation for IStatefulJob for more information. | ||
+ | ||
+## How do I stop a Job that is currently executing? | ||
+ | ||
+See the Quartz.IInterruptableJob interface, and the | ||
+Scheduler.Interrupt(string, string) method. | ||
+ | ||
+# Questions About Triggers | ||
+ | ||
+## How do I chain Job execution? Or, how do I create a workflow? | ||
+ | ||
+There currently is no "direct" or "free" way to chain triggers with Quartz. | ||
+However there are several ways you can accomplish it without much effort. | ||
+Below is an outline of a couple approaches: | ||
+ | ||
+One way is to use a listener (i.e. a TriggerListener, JobListener or | ||
+SchedulerListener) that can notice the completion of a job/trigger and then | ||
+immediately schedule a new trigger to fire. This approach can get a bit | ||
+involved, since you'll have to inform the listener which job follows which | ||
+- and you may need to worry about persistence of this information. | ||
+ | ||
+Another way is to build a Job that contains within its JobDataMap the name | ||
+of the next job to fire, and as the job completes (the last step in its | ||
+Execute() method) have the job schedule the next job. Several people are | ||
+doing this and have had good luck. Most have made a base (abstract) class | ||
+that is a Job that knows how to get the job name and group out of the | ||
+JobDataMap using special keys (constants) and contains code to schedule the | ||
+identified job. Then they simply make extensions of this class that included | ||
+the additional work the job should do. | ||
+ | ||
+In the future, Quartz will provide a much cleaner way to do this, but until | ||
+then, you'll have to use one of the above approaches, or think of yet another | ||
+that works better for you. | ||
+ | ||
+ | ||
+## Why isn't my trigger firing? | ||
+ | ||
+The most common reason for this is not having called Scheduler.Start(), | ||
+which tells the scheduler to start firing triggers. | ||
+ | ||
+The second most common reason is that the trigger or trigger group | ||
+has been paused. | ||
+ | ||
+## Daylight Saving Time and Triggers | ||
+ | ||
+ | ||
+CronTrigger and SimpleTrigger each handle daylight savings time in their own | ||
+way - each in the way that is intuitive to the trigger type. | ||
+ | ||
+ | ||
+ | ||
+First, as a review of what daylight savings time is, please read this resource: | ||
+http://webexhibits.org/daylightsaving/g.html . Some readers may be unaware | ||
+that the rules are different for different nations/contents. For example, | ||
+the 2005 daylight savings time starts in the United States on April 3, but | ||
+in Egypt on April 29. It is also important to know that not only the dates | ||
+are different for different locals, but the time of the shift is different | ||
+as well. Many places shift at 2:00 am, but others shift time at 1:00 am, | ||
+others at 3:00 am, and still others right at midnight. | ||
+ | ||
+ | ||
+ | ||
+SimpleTrigger allows you to schedule jobs to fire every N milliseconds. | ||
+As such, it has to do nothing in particular with respect to daylight | ||
+savings time in order to "stay on schedule" - it simply keeps firing every | ||
+N milliseconds. Regardless your SimpleTrigger is firing every 10 seconds, | ||
+or every 15 minutes, or every hour or every 24 hours it will continue to do | ||
+so. However the implication of this which confuses some users is that if | ||
+your SimpleTrigger is firing say every 12 hours, before daylight savings | ||
+switches it may be firing at what appears to be 3:00 am and 3:00 pm, | ||
+but after daylight savings 4:00 am and 4:00 pm. This is not a bug | ||
+- the trigger has kept firing exacly every N milliseconds, it just that the | ||
+"name" of that time that humans impose on that moment has changed. | ||
+ | ||
+ | ||
+ | ||
+CronTrigger allows you to schedule jobs to fire at certain moments with | ||
+respect to a "gregorian calendar". Hence, if you create a trigger to fire | ||
+every day at 10:00 am, before and after daylight savings time switches it | ||
+will continue to do so. However, depending on whether it was the Spring or | ||
+Autumn daylight savings event, for that particular Sunday, the actual time | ||
+interval between the firing of the trigger on Sundary morning at 10:00 am | ||
+since its firing on Saturday morning at 10:00 am will not be 24 hours, | ||
+but will instead be 23 or 25 hours respectively. | ||
+ | ||
+ | ||
+ | ||
+There is one additional point users must understand about CronTrigger with | ||
+respect to daylight savings. This is that you should take careful thought | ||
+about creating schedules that fire between midnight and 3:00 am (the critical | ||
+window of time depends on your trigger's locale, as explained above). | ||
+The reason is that depending on your trigger's schedule, and the particular | ||
+daylight event, the trigger may be skipped or may appear to not fire for an | ||
+hour or two. As examples, say you are in the United States, where daylight | ||
+savings events occur at 2:00 am. If you have a CronTrrigger that fires every | ||
+day at 2:15 am, then on the day of the beginning of daylight savings time | ||
+the trigger will be skipped, since, 2:15 am never occurs that day. If you | ||
+have a CronTrigger that fires every 15 minutes of every hour of every day, | ||
+then on the day daylight savings time ends you will have an hour of time | ||
+for which no triggerings occur, because when 2:00 am arrives, it will become | ||
+1:00 am again, however all of the firings during the one o'clock hour have | ||
+already occurred, and the trigger's next fire time was set to 2:00 am | ||
+- hence for the next hour no triggerings will occur. | ||
+ | ||
+ | ||
+ | ||
+In summary, all of this makes perfect sense, and should be easy to remember | ||
+if you keep these two rules in mind: | ||
+ | ||
+* SimpleTrigger ALWAYS fires exacly every N seconds, with no relation to the time of day. | ||
+* CronTrigger ALWAYS fires at a given time of day and then computes its next time to fire. If that time does not occur on a given day, the trigger will be skipped. If the time occurs twice in a given day, it only fires once, because after firing on that time the first time, it computes the next time of day to fire on. | ||
+ | ||
+# Questions About AdoJobStore | ||
+ | ||
+## How do I improve the performance of AdoJobStore? | ||
+ | ||
+There are a few known ways to speed up AdoJobStore, only one of which is | ||
+very practical. | ||
+ | ||
+First, the obvious, but not-so-practical: | ||
+ | ||
+* Buy a better (faster) network between the machine that runs Quartz, and the machine that runs your RDBMS. | ||
+* Buy a better (more powerful) machine to run your database on. | ||
+* Buy a better RDBMS. | ||
+ | ||
+Use driver delegate implementation that is specific to your database, like SQLServerDelegate, for best performance. | ||
+ | ||
+Now for something simple, but effective: Build indexes on the Quartz tables. | ||
+ | ||
+Most database systems will automatically put indexes on the primary-key | ||
+fields, many will also automatically do it for the foreign-key field. | ||
+Make sure yours does this, or make the indexes on all key fields | ||
+of every table manually. | ||
+ | ||
+Next, manually add some additional indexes: most important to index are | ||
+the TRIGGER table's "next_fire_time" and "state" fields. Last | ||
+(but not as important), add indexes to every column on the FIRED_TRIGGERS table. | ||
+ | ||
+**Create Table Indexes** | ||
+ | ||
+```sql | ||
+create index idx_qrtz_t_next_fire_time on qrtz_triggers(NEXT_FIRE_TIME); | ||
+create index idx_qrtz_t_state on qrtz_triggers(TRIGGER_STATE); | ||
+create index idx_qrtz_t_nf_st on qrtz_triggers(TRIGGER_STATE,NEXT_FIRE_TIME); | ||
+create index idx_qrtz_ft_trig_name on qrtz_fired_triggers(TRIGGER_NAME); | ||
+create index idx_qrtz_ft_trig_group on qrtz_fired_triggers(TRIGGER_GROUP); | ||
+create index idx_qrtz_ft_trig_name on qrtz_fired_triggers(TRIGGER_NAME); | ||
+create index idx_qrtz_ft_trig_n_g on qrtz_fired_triggers(TRIGGER_NAME,TRIGGER_GROUP); | ||
+create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(INSTANCE_NAME); | ||
+create index idx_qrtz_ft_job_name on qrtz_fired_triggers(JOB_NAME); | ||
+create index idx_qrtz_ft_job_group on qrtz_fired_triggers(JOB_GROUP); | ||
+``` |
22
_config.yml
@@ -0,0 +1,22 @@ | ||
+# Name of your blog (this will show up at the top of your page and in the RSS feed) | ||
+name: Quartz.NET Documentation | ||
+ | ||
+# Short description (goes below the title; it will also be used in the RSS feed) | ||
+description: | ||
+ | ||
+# Your name, as you want it to appear underneath each post and in the footer | ||
+author: Marko Lahma | ||
+ | ||
+category_dir: / | ||
+baseurl: | ||
+ | ||
+url: http://www.quartz-scheduler.net/ | ||
+ | ||
+#### Under the Hood Stuff ##### | ||
+ | ||
+markdown: redcarpet | ||
+pygments: true | ||
+ | ||
+exclude: [README.markdown, package.json, grunt.js, Gruntfile.js, node_modules, Gemfile, Gemfile.lock] | ||
+ | ||
+encoding: UTF-8 |

Oops, something went wrong.
0 comments on commit
baf4880