trinidad_scheduler_extension 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ == TrinidadScheduler Extension
2
+
3
+ Copyright (c) 2011 Brandon Dewitt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ == Additional Bundled Software
25
+
26
+ Quartz Scheduler is licensed according to the terms of Apache License, Version 2.0 (current). See http://www.apache.org/licenses/LICENSE-2.0 for details.
data/README ADDED
@@ -0,0 +1,127 @@
1
+ Trinidad Scheduler Extension
2
+ ===
3
+ Trinidad Scheduler uses Quartz to schedule processes for execution. It can be run as a server extension to Trinidad and/or a Web Application extension
4
+ for Trinidad. If run as a Server extension all schedulers will get the server configuration options each option that is defined at the Web Application
5
+ level will override the Server option.
6
+
7
+ Trinidad Scheduler creates a unique scheduler for each web application.
8
+
9
+ Most processes we schedule are scheduled using the *Cron* Trigger and *run_later*
10
+
11
+ Install Gem
12
+ ---
13
+ gem install trinidad_scheduler_extension
14
+
15
+ Configure Trinidad
16
+ ---
17
+ In either the Server *extensions* block or the Web Application *extentions* block add "scheduler"
18
+
19
+ extensions:
20
+ scheduler:
21
+
22
+ Example Usage
23
+ ---
24
+ It is valid to use the top level scheduling methods and run_later together
25
+
26
+ class ScheduledLog < TrinidadScheduler.Cron "0/5 * * * * ?"
27
+ def run
28
+ _logger.info "Executed every 5 seconds"
29
+
30
+ TrinidadScheduler.run_later do
31
+ _logger.info "Executed after a 3 second delay"
32
+ end
33
+ end
34
+ end
35
+
36
+ Laziness
37
+ ---
38
+ Trinidad Scheduler is very lazy. Schedulers will only be instantiated when they are needed to execute a job or to setup a schedule for execution.
39
+ This laziness extends to even runtime definition of classes and use of run_later in conditional statements. When a run_later block is encountered or
40
+ a class is defined at runtime that inherits from a TrinidadScheduler base method the scheduler will be created and started (if it does not exist)
41
+
42
+ If schedules are defined during application initialization then the scheduler will not be started until after the application is started by Tomcat.
43
+
44
+ (The lazy nature of TrinidadScheduler also gives the user time to define a logger outstide of the default configured log4j StdOut logger that
45
+ is included with TrinidadScheduler)
46
+
47
+ Usage
48
+ ===
49
+ The extension defines several methods that return classes based on the configuration options provided. These methods map to the scheduler trigger type
50
+ that Quartz provides. The implemented triggers are CronTrigger, SimpleTrigger, and DateIntervalTrigger.
51
+
52
+ Cron Trigger
53
+ ---
54
+ To define a process to be run based on a [cron expression] (http://en.wikipedia.org/wiki/CRON_expression#CRON_expression)
55
+
56
+ class ScheduledClass < TrinidadScheduler.Cron "0/5 * * * * ?"
57
+ def run
58
+ _logger.info "I am printed every 5 seconds"
59
+ end
60
+ end
61
+
62
+ The method *TrinidadScheduler.Cron* takes a cron expression as it's only argument and returns a class. This anonymous class is the parent of
63
+ ScheduledClass and does the work to wrap ScheduledClass for use as a CronTrigger in Quartz.
64
+
65
+ The instance method "run" must be defined because it is called when the scheduled process is triggered. *_logger* is an instance variable available
66
+ in ScheduledClass which gives the class access to the Quartz logger that is configured.
67
+
68
+ Simple Trigger
69
+ ---
70
+ Schedule an INFO log message every 5 seconds starting now, setting the end is not necessary in this context, but is done
71
+
72
+ class TestJob < TrinidadScheduler.Simple :start => Time.now, :end => Time.now + 240, :repeat 3, :interval => 5000
73
+ def run
74
+ _logger.info "I am inside this block" #=> prints "I am inside this block" every 5 seconds
75
+ end
76
+ end
77
+
78
+ The Simple Trigger will execute based on options passed to the method *TrinidadScheduler.Simple*, the options available are outlined
79
+ above in the example, none of them are necessary if you only want to trigger the process once. You can define a start and end time as well as how many
80
+ times to fire the trigger along with an interval to be observed between trigger execution.
81
+
82
+ DateInterval Trigger
83
+ ---
84
+ Schedule an INFO log message every 5 seconds starting now and ending after 4 minutes
85
+
86
+ class TestJob < TrinidadScheduler.DateInterval :start => Time.now, :end => Time.now + 240, :unit => :second, :interval => 5
87
+ def run
88
+ _logger.info "I am inside this block" #=> prints "I am inside this block" every 5 seconds
89
+ end
90
+ end
91
+
92
+ The DateInterval Trigger will execute a triggered process based on the configuration options passed. For more information on using the DateInterval
93
+ trigger consult the source.
94
+
95
+ run_later
96
+ ---
97
+ Schedules a block of code to run in another Thread after execution proceeds in the current Thread
98
+ *after the job runs it removes itself from the job scheduler
99
+
100
+ Using run_later with default 3 second delay
101
+
102
+ TrinidadScheduler.run_later do
103
+ _logger.info "I am inside this block" #=> prints "I am inside this block"
104
+ end
105
+
106
+ Using run_later with 20 second delay
107
+
108
+ TrinidadScheduler.run_later(:delay => 20) do
109
+ _logger.info "I am inside this block" #=> prints "I am inside this block"
110
+ end
111
+
112
+ Behind the scemes *run_later* is actually implemented using an anonymous class that inherits from TrinidadScheduler.Simple to schedule the run.
113
+
114
+
115
+ Inspiration
116
+ ---
117
+ Open Source software is a community effort - thanks to all, but the following were instrumental in the inspiration for TrinidadScheduler.
118
+
119
+ [techwhizbang] (https://github.com/techwhizbang/jruby-quartz) for handling of Quartz JobFactory
120
+ [why_metaid] (https://github.com/evaryont/why_metaid) for metaid extension
121
+ [TERRACOTTA] (http://www.terracotta.org/) for continued support Quartz Scheduler
122
+ [calavera] (https://github.com/calavera/trinidad) for Trinidad Server
123
+
124
+
125
+ Copyright
126
+ ---
127
+ Copyright (c) 2011 Brandon Dewitt<brandon+trinidad_scheduler@myjibe.com>. See LICENSE for details.
@@ -0,0 +1,22 @@
1
+ require 'java'
2
+
3
+ require 'trinidad'
4
+ require 'trinidad/jars'
5
+
6
+ # Jar files that are needed
7
+ require 'trinidad_scheduler_extension/jars/log4j-1.2.16'
8
+ require "trinidad_scheduler_extension/jars/slf4j-api-1.6.1"
9
+ require "trinidad_scheduler_extension/jars/slf4j-log4j12-1.6.1"
10
+ require "trinidad_scheduler_extension/jars/quartz-1.8.4"
11
+
12
+ # Trinidad Scheduler Extension files
13
+ require 'trinidad_scheduler_extension/version.rb'
14
+ require 'trinidad_scheduler_extension/trinidad_scheduler'
15
+ require 'trinidad_scheduler_extension/extensions/object'
16
+ require 'trinidad_scheduler_extension/scheduler_listener'
17
+ require 'trinidad_scheduler_extension/job_detail'
18
+ require 'trinidad_scheduler_extension/job_factory'
19
+ require 'trinidad_scheduler_extension/scheduled_job'
20
+ require 'trinidad_scheduler_extension/app_job'
21
+ require 'trinidad_scheduler_extension/scheduler_extension'
22
+
@@ -0,0 +1,152 @@
1
+ module TrinidadScheduler
2
+ module AppJob
3
+ include org.quartz.Job
4
+ include TrinidadScheduler::ScheduledJob
5
+
6
+ def self.included(other_obj)
7
+ new_job = TrinidadScheduler::JobDetail.new("#{ other_obj.job_detail_name rescue other_obj }", "#{other_obj}", other_obj)
8
+ begin
9
+ TrinidadScheduler[$servlet_context].schedule_job(new_job, other_obj.trigger)
10
+ rescue Exception => ex
11
+ raise JobError.new(ex)
12
+ end
13
+ end
14
+ end
15
+
16
+ # Method to schedule a block of code to run in another Thread after execution proceeds in the current Thread
17
+ # after the job runs it removes itself from the job scheduler
18
+ #
19
+ # @example Running run_later with default 3 second delay
20
+ # TrinidadScheduler.run_later do
21
+ # _logger.info "I am inside this block" #=> prints "I am inside this block"
22
+ # end
23
+ #
24
+ # @example Running run_later with 20 second delay
25
+ # TrinidadScheduler.run_later(:delay => 20) do
26
+ # _logger.info "I am inside this block" #=> prints "I am inside this block"
27
+ # end
28
+ #
29
+ # @param [Hash] opts the options for the process to be run
30
+ # @option opts [Integer] :delay the number of seconds delay before the block is triggered
31
+ # @param [Block] the block that will be run in a separate Thread after the delay
32
+ def self.run_later(opts={:delay=>3}, &blk)
33
+ Class.new(TrinidadScheduler.Simple :start => (Time.now + opts[:delay])) do
34
+ meta_def(:job_detail_name){ Time.now.to_i.to_s << Time.now.usec.to_s }
35
+ meta_def(:run_proc){ blk }
36
+
37
+ def run
38
+ self.class.run_proc.call
39
+ end
40
+ end
41
+ end
42
+
43
+ # Method to return an inheritable class for scheduling a CronTrigger Job
44
+ # the class that inherits from this method will have it's instance run method executed based on the cron_expression
45
+ #
46
+ # @example Schedule an INFO log message every 5 seconds
47
+ # class TestJob < TrinidadScheduler.Cron "0/5 * * * * ?"
48
+ # def run
49
+ # _logger.info "I am inside this block" #=> prints "I am inside this block" every 5 seconds
50
+ # end
51
+ # end
52
+ #
53
+ # @param [String] cron_expression the Cron Expression that defines the CronTrigger for the job class
54
+ # @return [Class] a new Class that is run by the CronTrigger that is defined
55
+ def self.Cron(cron_expression)
56
+ Class.new do
57
+ meta_def(:cron){ cron_expression }
58
+
59
+ def self.inherited(subclass)
60
+ meta_def :trigger do
61
+ org.quartz.CronTrigger.new("#{subclass}" + ".trigger", "#{subclass}", self.cron)
62
+ end
63
+
64
+ subclass.send(:include, TrinidadScheduler::AppJob)
65
+ end
66
+ end
67
+ end
68
+
69
+ # Method to return an inheritable class for scheduling a SimpleTrigger Job
70
+ # the class that inherits from this method will have it's instance run method executed based on the options passed
71
+ #
72
+ # @example Schedule an INFO log message every 5 seconds starting now, setting the end is not necessary in this context, but it done
73
+ # class TestJob < TrinidadScheduler.Simple :start => Time.now, :end => Time.now + 240, :repeat 3, :interval => 5000
74
+ # def run
75
+ # _logger.info "I am inside this block" #=> prints "I am inside this block" every 5 seconds
76
+ # end
77
+ # end
78
+ #
79
+ # @param [Hash] opts the options for the SimpleTrigger
80
+ # @option opts [java.util.Date, Time] :start the starting time of the trigger
81
+ # @option opts [java.util.Date, Time] :end the ending time of the trigger
82
+ # @option opts [Integer] :repeat the number of times to repeat the job (defaults to 0)
83
+ # @option opts [Integer] :interval the number of milliseconds between runs
84
+ # @return [Class] a new anonymous Class that is the parent of the Class run by the SimpleTrigger that is defined
85
+ def self.Simple(opts={})
86
+ opts[:start] ||= java.util.Date.new(Time.now.to_i*1000)
87
+ opts[:start] = java.util.Date.new(opts[:start].to_i*1000) if opts[:start].class == Time
88
+
89
+ opts[:end] ||= java.util.Date.new((Time.now + 10.years).to_i*1000)
90
+ opts[:end] = java.util.Date.new(opts[:end].to_i*1000) if opts[:end].class == Time
91
+
92
+ opts[:repeat] ||= 0
93
+ opts[:interval] ||= 0
94
+
95
+ Class.new do
96
+ meta_def(:opts){ opts }
97
+
98
+ def self.inherited(subclass)
99
+ meta_def :trigger do
100
+ org.quartz.SimpleTrigger.new("#{subclass}" + ".trigger", "#{subclass}",
101
+ self.opts[:start], self.opts[:end],
102
+ self.opts[:repeat], self.opts[:interval])
103
+ end
104
+
105
+ subclass.send(:include, TrinidadScheduler::AppJob)
106
+ end
107
+ end
108
+ end
109
+
110
+ # Method to return an inheritable class for scheduling a DateIntervalTrigger Job
111
+ # the class that inherits from this method will have it's instance run method executed based on the options passed
112
+ #
113
+ # @example Schedule an INFO log message every 5 seconds starting now and ending after 4 minutes
114
+ # class TestJob < TrinidadScheduler.DateInterval :start => Time.now, :end => Time.now + 240, :unit => :second, :interval => 5
115
+ # def run
116
+ # _logger.info "I am inside this block" #=> prints "I am inside this block" every 5 seconds
117
+ # end
118
+ # end
119
+ #
120
+ # @param [Hash] opts the options for the DateIntervalTrigger
121
+ # @option opts [java.util.Date, Time] :start the starting time of the trigger
122
+ # @option opts [java.util.Date, Time] :end the ending time of the trigger
123
+ # @option opts [Symbol, String] :unit the defined unit (:day, :second, :year, :month, :week)
124
+ # @option opts [Integer] :interval the number of units between runs
125
+ # @return [Class] a new anonymous Class that is the parent of the Class run by the SimpleTrigger that is defined
126
+ def self.DateInterval(opts={})
127
+ opts[:start] ||= java.util.Date.new(Time.now.to_i*1000)
128
+ opts[:start] = java.util.Date.new(opts[:start].to_i*1000) if opts[:start].class == Time
129
+
130
+ opts[:end] ||= java.util.Date.new((Time.now + 10.years).to_i*1000)
131
+ opts[:end] = java.util.Date.new(opts[:end].to_i*1000) if opts[:end].class == Time
132
+
133
+ opts[:unit] ||= :day
134
+ opts[:unit] = org.quartz.DateIntervalTrigger::IntervalUnit.value_of(opts[:unit].to_s.upcase)
135
+
136
+ opts[:interval] ||= 1
137
+
138
+ Class.new do
139
+ meta_def(:opts){ opts }
140
+
141
+ def self.inherited(subclass)
142
+ meta_def :trigger do
143
+ org.quartz.DateIntervalTrigger.new("#{subclass}" + ".trigger", "#{subclass}",
144
+ self.opts[:start], self.opts[:end],
145
+ self.opts[:unit], self.opts[:interval])
146
+ end
147
+
148
+ subclass.send(:include, TrinidadScheduler::AppJob)
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,11 @@
1
+ #
2
+ # our log4j properties / configuration file
3
+ #
4
+ # STDOUT appender
5
+ log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
6
+ log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
7
+ log4j.appender.STDOUT.layout.ConversionPattern=%d %p [%t] %C{1} - %m\n
8
+
9
+ # use the STDOUT appender. set the level to INFO.
10
+ log4j.rootLogger=INFO, STDOUT
11
+
@@ -0,0 +1,12 @@
1
+ # Metaid == a few simple metaclass helper
2
+ # (See http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html.)
3
+ class Object
4
+ # The hidden singleton lurks behind everyone
5
+ def metaclass; class << self; self; end; end
6
+ def meta_eval &blk; metaclass.instance_eval &blk; end
7
+
8
+ # Adds methods to a metaclass
9
+ def meta_def name, &blk
10
+ meta_eval { define_method name, &blk }
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module TrinidadScheduler
2
+ class JobDetail < org.quartz.JobDetail
3
+
4
+ attr_accessor :job
5
+
6
+ def initialize(name, group, job_class)
7
+ super()
8
+ set_name name
9
+ set_group group
10
+ @job = job_class.new
11
+ end
12
+
13
+ def validate()
14
+ raise org.quartz.SchedulerException.new("Job's name cannot be null",
15
+ org.quartz.SchedulerException.ERR_CLIENT_ERROR) if get_name == nil
16
+ raise org.quartz.SchedulerException.new("Job's group cannot be null",
17
+ org.quartz.SchedulerException.ERR_CLIENT_ERROR) if get_group == nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ module TrinidadScheduler
2
+ class JobFactory
3
+ include org.quartz.spi.JobFactory
4
+
5
+ def new_job bundle
6
+ bundle.get_job_detail.job
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ module TrinidadScheduler
2
+ module ScheduledJob
3
+ class JobError < StandardError; end
4
+
5
+ attr_accessor :_context
6
+ attr_accessor :_logger
7
+
8
+ def run
9
+ raise "Implement a [run] method if you are going to use #{self.class} as a job class"
10
+ end
11
+
12
+ def execute(context)
13
+ begin
14
+ @_context = context
15
+ @_logger = org.apache.log4j.Logger.getLogger("#{self.class}")
16
+ run()
17
+ rescue Exception => ex
18
+ raise JobError.new(ex)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ module Trinidad
2
+ module Extensions
3
+
4
+ class SchedulerWebAppExtension < WebAppExtension
5
+
6
+ def configure(tomcat, app_context)
7
+ app_context.add_lifecycle_listener(TrinidadScheduler::WebAppListener.new(app_context.servlet_context, @options))
8
+ end
9
+ end
10
+
11
+ class SchedulerServerExtension < ServerExtension
12
+
13
+ def configure(tomcat)
14
+ tomcat.get_host.add_container_listener(TrinidadScheduler::GlobalListener.new(@options))
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module TrinidadScheduler
2
+ class WebAppListener
3
+ include org.apache.catalina.LifecycleListener
4
+
5
+ def initialize(servlet_context, options)
6
+ @servlet_context = servlet_context
7
+ @options = options
8
+ TrinidadScheduler.store_scheduler_options(@servlet_context, @options)
9
+ end
10
+
11
+ def needs_started?
12
+ TrinidadScheduler.scheduler_exists?(@servlet_context) && !TrinidadScheduler[@servlet_context].is_started
13
+ end
14
+
15
+ def lifecycle_event(event)
16
+ case event.type
17
+ when org.apache.catalina.Lifecycle::START_EVENT then
18
+ if needs_started?
19
+ TrinidadScheduler[@servlet_context].start
20
+ TrinidadScheduler[@servlet_context].resume_all
21
+ end
22
+
23
+ TrinidadScheduler.set_servlet_started(@servlet_context)
24
+ end
25
+ end
26
+ end
27
+
28
+ class GlobalListener
29
+ include org.apache.catalina.ContainerListener
30
+
31
+ def initialize(options)
32
+ @options = options
33
+ end
34
+
35
+ def container_event(event)
36
+ case event.type
37
+ when org.apache.catalina.Container::ADD_CHILD_EVENT then
38
+ event.data.add_lifecycle_listener(TrinidadScheduler::WebAppListener.new(event.data.servlet_context, @options))
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,131 @@
1
+ module TrinidadScheduler
2
+ CONFIG_HOME = File.expand_path(File.dirname(__FILE__) + "/trinidad_scheduler_extension/config")
3
+ JAR_HOME = File.expand_path(File.dirname(__FILE__) + "/trinidad_scheduler_extension/jars")
4
+
5
+ # Sets log4j properties if not established by Application Servers
6
+ # TrinidadScheduler is really lazy so this is only set when a scheduler is needed
7
+ def self.trinidad_scheduler_init_log4j
8
+ if java.lang.System.get_property('log4j.configuration').nil?
9
+ java.lang.System.set_property('log4j.configuration', java.io.File.new("#{CONFIG_HOME}/log4j.properties").to_url.to_s)
10
+ end
11
+ end
12
+
13
+ # Standardizing the naming of the variables that are stored on the context
14
+ def self.context_path(path)
15
+ path.gsub("/", "") == "" ? "Default" : path.gsub("/", "").capitalize
16
+ end
17
+
18
+ # Assists in lazily evaluating if a scheduler is needed for a context
19
+ #
20
+ # @param [ServletContext] context
21
+ # @return [Boolean]
22
+ def self.scheduler_exists?(context)
23
+ !!context.get_attribute(scheduler_name(context))
24
+ end
25
+
26
+ # Tomcat event callbacks are good for static systems but JRuby allows dynamic definition of classes and function
27
+ # so I am storing a variable on the servlet context that allow the extension to check if the servlet has been started
28
+ # during lazy evaluation of the need for a scheduler and/or starting the scheduler
29
+ #
30
+ # @param [ServletContext] context
31
+ # @return [Boolean]
32
+ def self.servlet_started?(context)
33
+ !!context.get_attribute(started_name(context))
34
+ end
35
+
36
+ # Helper to centralize the operations on the servlet contexts, sets the servlet started variable when the context is started, reguardless of whether
37
+ # a scheduler exists or not
38
+ #
39
+ # @param [ServletContext] context
40
+ def self.set_servlet_started(context)
41
+ context.set_attribute(started_name(context), true)
42
+ end
43
+
44
+ # Helper method that attaches the configuration options from the Trinidad config file to the ServletContext
45
+ #
46
+ # @param [ServletContext] context
47
+ # @param [Hash] options
48
+ def self.store_scheduler_options(context, options)
49
+ context.set_attribute(options_name(context), options)
50
+ end
51
+
52
+ # Centralized definition of where variables will be stored on the ServletContext
53
+ def self.started_name(context)
54
+ "TrinidadScheduler::#{context_path(context.context_path)}::ServletStarted"
55
+ end
56
+
57
+ def self.options_name(context)
58
+ "TrinidadScheduler::#{context_path(context.context_path)}::SchedulerOptions"
59
+ end
60
+
61
+ def self.scheduler_name(context)
62
+ "TrinidadScheduler::#{context_path(context.context_path)}::Scheduler"
63
+ end
64
+
65
+ # Bracket accessor defined to retreive the scheduler for a context
66
+ # if no scheduler is attached to the context then one is created and attached at time of access and returned
67
+ #
68
+ # @param [ServletContext] context
69
+ # @return [org.quartz.impl.StdScheduler]
70
+ def self.[](context)
71
+ if !scheduler_exists?(context)
72
+ self.trinidad_scheduler_init_log4j
73
+ self[context] = self.quartz_scheduler(context, context.get_attribute(options_name(context)))
74
+ end
75
+
76
+ scheduler = context.get_attribute(scheduler_name(context))
77
+
78
+ if !scheduler.is_started && servlet_started?(context)
79
+ scheduler.start
80
+ scheduler.resume_all
81
+ end
82
+
83
+ return scheduler
84
+ end
85
+
86
+ # Bracket assignment operator, will attach the scheduler passed to the context in the brackets
87
+ #
88
+ # @param [ServletContext] context
89
+ # @param [org.quartz.impl.StdScheduler] scheduler
90
+ def self.[]=(context, scheduler)
91
+ context.set_attribute(scheduler_name(context), scheduler)
92
+ end
93
+
94
+ # Method to build and return Quartz schedulers
95
+ #
96
+ # @param [ServletContext] context
97
+ # @param [Hash] opts, the options to configure the scheduler with
98
+ def self.quartz_scheduler(context, opts={})
99
+ options = {:wrapped => false, :thread_count => 10, :thread_priority => 5}
100
+ options.merge!(opts)
101
+ options[:name] = context_path(context.context_path)
102
+
103
+ scheduler_factory = org.quartz.impl.StdSchedulerFactory.new
104
+ scheduler_factory.initialize(quartz_properties(options))
105
+ scheduler = scheduler_factory.get_scheduler
106
+ scheduler.set_job_factory(TrinidadScheduler::JobFactory.new)
107
+ scheduler.pause_all
108
+ return scheduler
109
+ end
110
+
111
+ # Properties stream for initializing a scheduler
112
+ # Currently restricts schedulers to RAMJobStore and SimpleThreadPool
113
+ def self.quartz_properties(opts={})
114
+ prop_string = java.lang.String.new("
115
+ org.quartz.scheduler.rmi.export = false
116
+ org.quartz.scheduler.rmi.proxy = false
117
+ org.quartz.scheduler.wrapJobExecutionInUserTransaction = #{opts[:wrapped]}
118
+ org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
119
+ org.quartz.threadPool.threadCount = #{opts[:thread_count]}
120
+ org.quartz.threadPool.threadPriority = #{opts[:thread_priority]}
121
+ org.quartz.threadPool.threadNamePrefix = WorkerThread::#{opts[:name]}
122
+ org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
123
+ org.quartz.jobStore.misfireThreshold = 60000
124
+ org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore")
125
+
126
+ qp = java.util.Properties.new
127
+ qp.load(java.io.ByteArrayInputStream.new(prop_string.getBytes()))
128
+ qp.set_property("org.quartz.scheduler.instanceName", "Quartz::#{opts[:name]}::Application")
129
+ return qp
130
+ end
131
+ end
@@ -0,0 +1,3 @@
1
+ module TrinidadScheduler
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trinidad_scheduler_extension
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Brandon Dewitt
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-03-06 00:00:00 -05:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: trinidad_jars
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: Extension to support scheduled jobs in Trinidad
28
+ email: brandon+trinidad_scheduler@myjibe.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files:
34
+ - LICENSE
35
+ - README
36
+ files:
37
+ - LICENSE
38
+ - README
39
+ - lib/trinidad_scheduler_extension.rb
40
+ - lib/trinidad_scheduler_extension/app_job.rb
41
+ - lib/trinidad_scheduler_extension/config/log4j.properties
42
+ - lib/trinidad_scheduler_extension/extensions/object.rb
43
+ - lib/trinidad_scheduler_extension/jars/log4j-1.2.16.jar
44
+ - lib/trinidad_scheduler_extension/jars/quartz-1.8.4.jar
45
+ - lib/trinidad_scheduler_extension/jars/slf4j-api-1.6.1.jar
46
+ - lib/trinidad_scheduler_extension/jars/slf4j-log4j12-1.6.1.jar
47
+ - lib/trinidad_scheduler_extension/job_detail.rb
48
+ - lib/trinidad_scheduler_extension/job_factory.rb
49
+ - lib/trinidad_scheduler_extension/scheduled_job.rb
50
+ - lib/trinidad_scheduler_extension/scheduler_extension.rb
51
+ - lib/trinidad_scheduler_extension/scheduler_listener.rb
52
+ - lib/trinidad_scheduler_extension/trinidad_scheduler.rb
53
+ - lib/trinidad_scheduler_extension/version.rb
54
+ has_rdoc: true
55
+ homepage: https://github.com/bdewitt/trinidad_scheduler_extension
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.6.1
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: "Extension to support scheduled jobs in Trinidad: Extension"
82
+ test_files: []
83
+