Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Create gh-pages branch via GitHub
  • Loading branch information
lahma committed Jan 6, 2014
1 parent ba188cc commit baf4880
Show file tree
Hide file tree
Showing 43 changed files with 2,733 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .gitattributes
@@ -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
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
/_site
/*.lock
1 change: 1 addition & 0 deletions CNAME
@@ -0,0 +1 @@
www.quartz-scheduler.net
304 changes: 304 additions & 0 deletions FAQ.md
@@ -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);
```
2 changes: 2 additions & 0 deletions Gemfile
@@ -0,0 +1,2 @@
source 'https://rubygems.org'
gem 'github-pages'
22 changes: 22 additions & 0 deletions _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

0 comments on commit baf4880

Please sign in to comment.