say_when 1.0.0 → 2.0.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/Guardfile +50 -0
  5. data/README.md +135 -2
  6. data/Rakefile +1 -0
  7. data/lib/say_when.rb +33 -18
  8. data/lib/say_when/configuration.rb +16 -0
  9. data/lib/say_when/cron_expression.rb +19 -21
  10. data/lib/say_when/poller/base_poller.rb +108 -0
  11. data/lib/say_when/poller/celluloid_poller.rb +30 -0
  12. data/lib/say_when/poller/concurrent_poller.rb +31 -0
  13. data/lib/say_when/poller/simple_poller.rb +37 -0
  14. data/lib/say_when/processor/active_job_strategy.rb +35 -0
  15. data/lib/say_when/processor/simple_strategy.rb +13 -0
  16. data/lib/say_when/processor/test_strategy.rb +21 -0
  17. data/lib/say_when/scheduler.rb +67 -101
  18. data/lib/say_when/storage/active_record_strategy.rb +204 -0
  19. data/lib/say_when/storage/base_job.rb +96 -0
  20. data/lib/say_when/storage/memory_strategy.rb +140 -0
  21. data/lib/say_when/tasks.rb +15 -3
  22. data/lib/say_when/triggers/base.rb +3 -3
  23. data/lib/say_when/triggers/cron_strategy.rb +2 -3
  24. data/lib/say_when/triggers/instance_strategy.rb +3 -4
  25. data/lib/say_when/triggers/once_strategy.rb +3 -4
  26. data/lib/say_when/utils.rb +16 -0
  27. data/lib/say_when/version.rb +1 -1
  28. data/say_when.gemspec +10 -5
  29. data/test/minitest_helper.rb +45 -15
  30. data/test/say_when/configuration_test.rb +14 -0
  31. data/test/say_when/cron_expression_test.rb +140 -0
  32. data/test/say_when/poller/base_poller_test.rb +42 -0
  33. data/test/say_when/poller/celluloid_poller_test.rb +17 -0
  34. data/test/say_when/poller/concurrent_poller_test.rb +19 -0
  35. data/test/say_when/poller/simple_poller_test.rb +27 -0
  36. data/test/say_when/processor/active_job_strategy_test.rb +31 -0
  37. data/test/say_when/processor/simple_strategy_test.rb +15 -0
  38. data/test/say_when/scheduler_test.rb +41 -57
  39. data/test/say_when/storage/active_record_strategy_test.rb +134 -0
  40. data/test/say_when/storage/memory_strategy_test.rb +96 -0
  41. data/test/say_when/triggers/cron_strategy_test.rb +11 -0
  42. data/test/say_when/triggers/instance_strategy_test.rb +13 -0
  43. data/test/say_when/triggers/once_strategy_test.rb +2 -2
  44. data/test/say_when_test.rb +20 -0
  45. metadata +110 -36
  46. data/lib/say_when/base_job.rb +0 -96
  47. data/lib/say_when/processor/active_messaging.rb +0 -21
  48. data/lib/say_when/processor/base.rb +0 -19
  49. data/lib/say_when/processor/shoryuken.rb +0 -14
  50. data/lib/say_when/processor/simple.rb +0 -17
  51. data/lib/say_when/storage/active_record/acts.rb +0 -92
  52. data/lib/say_when/storage/active_record/job.rb +0 -100
  53. data/lib/say_when/storage/active_record/job_execution.rb +0 -14
  54. data/lib/say_when/storage/memory/base.rb +0 -36
  55. data/lib/say_when/storage/memory/job.rb +0 -53
  56. data/test/say_when/cron_expression_spec.rb +0 -74
  57. data/test/say_when/processor/active_messaging_test.rb +0 -41
  58. data/test/say_when/storage/active_record/job_test.rb +0 -90
  59. data/test/say_when/storage/memory/job_test.rb +0 -32
  60. data/test/say_when/storage/memory/trigger_test.rb +0 -54
  61. data/test/support/models.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5f6591f3f5206b517960a08efa500fbf3334ff56
4
- data.tar.gz: 4daa2a598bf163817da9b7987938cc7216ed1f58
3
+ metadata.gz: 92b39148a95c13f3b9fc5d55d56ef49d3566576f
4
+ data.tar.gz: d30b25ecd756ae2eb187a70c7511578fb0ddfc74
5
5
  SHA512:
6
- metadata.gz: 236e345d76fb90f946e90a6d7ed8581bf670823b36965da9110e680f39847656c309e00ecc77d931e113a27648bc29bc37f72223f9a32c94f45a240c64fbff47
7
- data.tar.gz: 3eb871a517e9e1c7246d7b52957b423c56fc58d47127f1523d2383a6f605314901684ad2a21c70bc3bd620964f6346403d3bf9e10ec70a79a9192a6cb55fda13
6
+ metadata.gz: 62ac59b8bd6d443cde57281aa883e3aaedba830737c4c9ea296914fd1c032628c9d316b5b9f920895bcc226694ab9e1568eb03dee8a759533cca671cb6afac3f
7
+ data.tar.gz: 0a30ee197ca109d14c57377f1c55c48d9e8f3b337a7a062dab0c93adf70e508e942e825420cbde5eb8b6fee2ec61a7a174ebb58be93081a55d8644dc5ec13156
data/.gitignore CHANGED
@@ -14,3 +14,4 @@
14
14
  *.DS_Store
15
15
  .ruby-version
16
16
  test/db/test.db
17
+ notes.md
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - "2.2.4"
5
+ - "2.3.1"
data/Guardfile ADDED
@@ -0,0 +1,50 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features)
6
+
7
+ ## Uncomment to clear the screen before every task
8
+ # clearing :on
9
+
10
+ ## Guard internally checks for changes in the Guardfile and exits.
11
+ ## If you want Guard to automatically start up again, run guard in a
12
+ ## shell loop, e.g.:
13
+ ##
14
+ ## $ while bundle exec guard; do echo "Restarting Guard..."; done
15
+ ##
16
+ ## Note: if you are using the `directories` clause above and you are not
17
+ ## watching the project directory ('.'), then you will want to move
18
+ ## the Guardfile to a watched dir and symlink it back, e.g.
19
+ #
20
+ # $ mkdir config
21
+ # $ mv Guardfile config/
22
+ # $ ln -s config/Guardfile .
23
+ #
24
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
25
+
26
+ guard :minitest do
27
+ # with Minitest::Unit
28
+ watch(%r{^test/(.*)\/?(.*)_test\.rb$})
29
+ watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
30
+ watch(%r{^test/minitest_helper\.rb$}) { 'test' }
31
+
32
+ # with Minitest::Spec
33
+ # watch(%r{^spec/(.*)_spec\.rb$})
34
+ # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
35
+ # watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
36
+
37
+ # Rails 4
38
+ # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
39
+ # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' }
40
+ # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
41
+ # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
42
+ # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" }
43
+ # watch(%r{^test/.+_test\.rb$})
44
+ # watch(%r{^test/test_helper\.rb$}) { 'test' }
45
+
46
+ # Rails < 4
47
+ # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
48
+ # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" }
49
+ # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
50
+ end
data/README.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # SayWhen
2
2
 
3
- TODO: Write a gem description
3
+ SayWhen is a job scheduling library for use in any project, but with a few extra hooks for rails projects.
4
+ It was roughly inspired by the [Quartz scheduler](http://quartz-scheduler.org/).
5
+
6
+ You add it to a ruby program (optionally configure it) and then schedule jobs using a few different strategies, with cron-like expressions the most powerful.
7
+
8
+ When scheduling, you specify a trigger which controls when execution will occur, such as a cron trigger, or an execute only once trigger, and a job, which is the actual work to perform.
9
+
10
+ The cron triggers are based on the [extended cron capabilities](http://wiki.opensymphony.com/display/QRTZ1/CronTriggers+Tutorial).
11
+
12
+ Jobs can be stored different ways, either in memory (e.g. loaded on start from a ruby file), or saved to a database.
13
+
14
+ The scheduler can execute the jobs in different ways, either by loading and running them itself synchronously, or by delegating the processing to ActiveJob.
15
+
16
+ SayWhen can be run either in its own process, or can run as a supervised actor in a Celluloid process (e.g. sidekiq or shoryuken).
4
17
 
5
18
  ## Installation
6
19
 
@@ -18,9 +31,129 @@ Or install it yourself as:
18
31
 
19
32
  $ gem install say_when
20
33
 
34
+ ## Configuration
35
+
36
+ To use, first configure how jobs are stored and processed.
37
+ Be default, they are in memory, and processed synchronously, but that can be configured to behave differently.
38
+
39
+ The currently available storage options are:
40
+ - Memory (default) - usually jobs are initialized in code on load
41
+ - ActiveRecord - stores the scheduled jobs and can log execution information to database tables
42
+
43
+ The processor options are:
44
+ - Simple - the scheduler process executes the job itself synchronously
45
+ - ActiveJob - delegates the work to an ActiveJob async call
46
+ - Test - stubs out processing, useful for testing only
47
+
48
+ You also have some options for running SayWhen:
49
+ - SimplePoller - just a simple looping process, can be started with rake
50
+ - CelluloidPoller - defines a Celluloid Actor appropriate for adding to a running Celluloid process, such as from Shoryuken
51
+
52
+ Finally, there are options for triggers that determine when jobs run:
53
+ - Cron expression
54
+ - Once
55
+ - Instance
56
+
57
+ ```ruby
58
+ # config/intializers/say_when.rb
59
+
60
+ require 'say_when'
61
+
62
+ # you can specify a the logger
63
+ SayWhen.logger = Rails.logger
64
+
65
+ # configure the scheduler for how to store and process scheduled jobs
66
+ # it will default to a :memory strategy and :simple processor
67
+ SayWhen.configure do |options|
68
+ options[:storage_strategy] = :active_record
69
+ options[:processor_strategy] = :simple
70
+ end
71
+ ```
72
+
21
73
  ## Usage
22
74
 
23
- TODO: Write usage instructions here
75
+ ### Basics
76
+ There is a very verbose way to create a scheduled job, setting the options for the trigger and job explicitly, and then some helper methods that make this easier for common cases.
77
+
78
+ Here is an example of the verbose way of scheduling a job, which is a good place to start:
79
+ ```ruby
80
+
81
+ job = SayWhen::Scheduler.schedule(
82
+ trigger_strategy: 'once',
83
+ trigger_options: { at: 10.second.since },
84
+ job_class: SomeTask,
85
+ job_method: 'execute',
86
+ data: { id: 123 }
87
+ )
88
+ ```
89
+
90
+ There are also convenience methods on the `Scheduler`:
91
+ ```ruby
92
+
93
+ ```
94
+ ## ActiveRecord integration
95
+
96
+ Besides storing jobs in ActiveRecord, you can also associate jobs with other models.
97
+
98
+ There is an `acts_as_scheduled` method you can call in an ActiveRecord class for this purpose.
99
+ It both makes it easier to schedule a job, and to see manage the list of related jobs.
100
+
101
+ For example, you might create a job to send a reminder a week after a user is created, and relate this new job to that user.
102
+ By associating it with the `ActiveRecord` object, you can more easily manage this reminder, such as canceling it if they close their account.
103
+
104
+ When using `ActiveRecord` integration in Rails, there is a generator for the migration to create the tables for saving scheduled jobs:
105
+ ```
106
+ bundle exec rails generate say_when:migration
107
+ ```
108
+
109
+ The resulting migration assumes the scheduled jobs will use a integer based id column, please update the default migration if this is not the case in your system:
110
+ ```ruby
111
+ # change this to string or other type as needed
112
+ t.integer :scheduled_id
113
+ ```
114
+
115
+ ## Pollers
116
+
117
+ The `SimplePoller` does what you would expect; when you run it, it starts up a loop of checking for jobs to run, sleeping, and then checking again.
118
+
119
+ It can be executed from the rake task:
120
+ ```
121
+ bundle exec rake say_when:start
122
+ ```
123
+
124
+ But that isn't doing much except loading the environment then this:
125
+ ```ruby
126
+ require 'say_when'
127
+ require 'say_when/poller/simple_poller'
128
+
129
+ SayWhen::Poller::SimplePoller.start
130
+ ```
131
+
132
+ For my own purposes, I use things like `daemontools` and `god` to daemonize, so this has been enough for me, but it would not be hard to write a command line script for it.
133
+
134
+ Most of the time I am also running a job processor, either `shoryuken` or `sidekiq`, and I would prefer to piggyback on that same process instead of starting up another. Since both of those use Celluloid (or did, Sidekiq no longer does), I also created a Celluloid actor class that can be added to the celluloid based job process via hooks in their startup.
135
+
136
+ For Shoryuken, add this to your initializer (probably `config/initializers/shoryuken.rb`):
137
+ ```ruby
138
+ require 'say_when/poller/celluloid_poller'
139
+
140
+ Shoryuken.on_start do
141
+ # check for new jobs to run every 5 seconds
142
+ SayWhen::Poller::CelluloidPoller.supervise_as :say_when, 5
143
+ end
144
+ ```
145
+
146
+ For Sidekiq, there is a slightly different syntax, but basically the same idea
147
+ (via https://github.com/mperham/sidekiq/wiki/Deployment#events):
148
+ ```ruby
149
+ require 'say_when/poller/celluloid_poller'
150
+
151
+ Sidekiq.configure_server do |config|
152
+ config.on(:startup) do
153
+ SayWhen::Poller::CelluloidPoller.supervise_as :say_when, 5
154
+ end
155
+ end
156
+ ```
24
157
 
25
158
  ## Contributing
26
159
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
+ require 'say_when/tasks'
3
4
 
4
5
  Rake::TestTask.new(:test) do |t|
5
6
  t.libs << 'test'
data/lib/say_when.rb CHANGED
@@ -1,32 +1,47 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'active_support'
3
+ require 'active_support/all'
4
4
 
5
- require "say_when/version"
6
- require 'say_when/base_job'
5
+ require 'say_when/version'
6
+ require 'say_when/configuration'
7
+ require 'say_when/utils'
7
8
  require 'say_when/cron_expression'
8
- require 'say_when/processor/base'
9
- require 'say_when/processor/simple'
10
9
  require 'say_when/scheduler'
11
10
 
12
- require 'say_when/processor/active_messaging' if defined?(::ActiveMessaging)
13
- require 'say_when/processor/shoryuken' if defined?(::Shoryuken)
14
- require 'say_when/storage/active_record/job' if defined?(::ActiveRecord)
15
11
  require 'say_when/railtie' if defined?(Rails)
16
12
 
17
13
  module SayWhen
18
- def SayWhen.logger=(logger)
19
- @@logger = logger
20
- end
21
-
22
- def SayWhen.logger
23
- if !defined?(@@logger) || !@@logger
24
- if defined?(Rails.logger) && Rails.logger
25
- @@logger = Rails.logger
14
+ class << self
15
+ def logger
16
+ @logger ||= if defined?(Rails)
17
+ Rails.logger
18
+ else
19
+ Logger.new(STDOUT)
26
20
  end
21
+ end
22
+
23
+ def logger=(l)
24
+ @logger = l
25
+ end
26
+
27
+ def options
28
+ @options ||= SayWhen::Configuration.default_options
29
+ end
30
+
31
+ def configure(opts = {})
32
+ @lock ||= Mutex.new
33
+ options.merge(opts)
34
+ yield options if block_given?
35
+ end
36
+
37
+ def scheduler
38
+ return @scheduler if defined?(@scheduler) && @scheduler
39
+ @lock.synchronize { @scheduler = SayWhen::Scheduler.new }
40
+ @scheduler
41
+ end
27
42
 
28
- @@logger = Logger.new(STDOUT) unless defined?(@@logger)
43
+ def schedule(job)
44
+ scheduler.schedule(job)
29
45
  end
30
- @@logger
31
46
  end
32
47
  end
@@ -0,0 +1,16 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+
4
+ module SayWhen
5
+ class Configuration
6
+ def self.default_options
7
+ {}.tap do |defaults|
8
+ defaults[:processor_strategy] = :simple
9
+ defaults[:storage_strategy] = :memory
10
+ defaults[:tick_length] = (ENV['SAY_WHEN_TICK_LENGTH'] || '5').to_i
11
+ defaults[:queue] = ENV['SAY_WHEN_QUEUE'] || 'default'
12
+ defaults[:reset_acquired_length] = (ENV['SAY_WHEN_RESET_ACQUIRED_LENGTH'] || '3600').to_i
13
+ end
14
+ end
15
+ end
16
+ end
@@ -3,14 +3,13 @@
3
3
  require 'date'
4
4
 
5
5
  module SayWhen
6
-
7
6
  # Based on the extended cron capabilties
8
- # http://wiki.opensymphony.com/display/QRTZ1/CronTriggers+Tutorial
7
+ # http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-06.html
9
8
  class CronExpression
10
9
  attr_reader :expression
11
10
  attr_accessor :time_zone, :seconds, :minutes, :hours, :days_of_month, :months, :days_of_week, :years
12
11
 
13
- def initialize(expression, time_zone=nil)
12
+ def initialize(expression = {}, time_zone = nil)
14
13
  if expression.is_a?(Hash)
15
14
  opts = expression
16
15
 
@@ -28,19 +27,14 @@ module SayWhen
28
27
  "#{opts[:seconds]} #{opts[:minutes]} #{opts[:hours]} #{opts[:days_of_month]} #{opts[:months]} #{opts[:days_of_week]} #{opts[:years]}"
29
28
  end
30
29
 
31
- self.time_zone = if opts.has_key?(:time_zone) && !opts[:time_zone].blank?
32
- opts[:time_zone]
33
- else
34
- Time.zone.nil? ? "UTC" : Time.zone.name
35
- end
36
-
30
+ @time_zone = opts[:time_zone]
37
31
  else
38
32
  @expression = expression
39
- self.time_zone = if time_zone.blank?
40
- Time.zone.nil? ? "UTC" : Time.zone.name
41
- else
42
- time_zone
43
- end
33
+ end
34
+
35
+ @time_zone ||= time_zone
36
+ if @time_zone.blank?
37
+ @time_zone = Time.zone.try(:name) || "UTC"
44
38
  end
45
39
 
46
40
  parse
@@ -122,7 +116,6 @@ module SayWhen
122
116
  [before, false]
123
117
  end
124
118
 
125
-
126
119
  end
127
120
 
128
121
  class CronValue
@@ -154,19 +147,24 @@ module SayWhen
154
147
  values = []
155
148
  case val
156
149
  #check for a '/' for increments
157
- when /(\w+)\/(\d+)/ then (( $1 == "*") ? min : $1.to_i).step(max, $2.to_i) { |x| values << x }
150
+ when /(.+)\/(\d+)/
151
+ (( $1 == "*") ? min : $1.to_i).step(max, $2.to_i) { |x| values << x }
158
152
 
159
153
  #check for ',' for list of values
160
- when /(\d+)(,\d+)+/ then values = val.split(',').map{ |v| v.to_i }.sort
154
+ when /(\d+)(,\d+)+/
155
+ values = val.split(',').map{ |v| v.to_i }.sort
161
156
 
162
157
  #check for '-' for range of values
163
- when /(\d+)-(\d+)/ then values = (($1.to_i)..($2.to_i)).to_a
158
+ when /(\d+)-(\d+)/
159
+ values = (($1.to_i)..($2.to_i)).to_a
164
160
 
165
161
  #check for '*' for all values between min and max
166
- when /^(\*)$/ then values = (min..max).to_a
162
+ when /^(\*)$/
163
+ values = (min..max).to_a
167
164
 
168
165
  #lastly, should just be a number
169
- when /^(\d+)$/ then values << $1.to_i
166
+ when /^(\d+)$/
167
+ values << $1.to_i
170
168
 
171
169
  #if nothing else, leave values as []
172
170
  else values = []
@@ -535,7 +533,7 @@ module SayWhen
535
533
 
536
534
  class YearsCronValue < CronValue
537
535
  def initialize(exp)
538
- super(:year, 1970, 2099, exp)
536
+ super(:year, 1970, (Date.today.year + 100), exp)
539
537
  end
540
538
 
541
539
  def next(date)
@@ -0,0 +1,108 @@
1
+ # encoding: utf-8
2
+
3
+ require 'say_when/utils'
4
+
5
+ module SayWhen
6
+ module Poller
7
+ module BasePoller
8
+ def self.included(mod)
9
+ mod.include(SayWhen::Utils)
10
+ attr_accessor :reset_next_at
11
+ end
12
+
13
+ def stop
14
+ end
15
+
16
+ def start
17
+ end
18
+
19
+ def reset_acquired
20
+ time_now = Time.now
21
+ self.reset_next_at ||= time_now
22
+
23
+ if reset_acquired_length > 0 && reset_next_at <= time_now
24
+ self.reset_next_at = time_now + reset_acquired_length
25
+ logger.debug "SayWhen:: reset acquired at #{time_now}, try again at #{reset_next_at}"
26
+ storage.reset_acquired(reset_acquired_length)
27
+ end
28
+ end
29
+
30
+ def job_error(msg, job, ex)
31
+ job_msg = job && " job:'#{job.inspect}'"
32
+ logger.error "#{self.class.name} #{msg}#{job_msg}: #{ex.message}\n\t#{ex.backtrace.join("\t\n")}"
33
+ release(job)
34
+ end
35
+
36
+ def process_jobs
37
+ reset_acquired
38
+ time_now = Time.now
39
+ while job = acquire(time_now)
40
+ process(job, time_now)
41
+ time_now = Time.now
42
+ end
43
+ rescue StandardError => ex
44
+ job_error("Error!", job, ex)
45
+ tick(error_tick_length)
46
+ rescue Interrupt => ex
47
+ job_error("Interrupt!", job, ex)
48
+ raise ex
49
+ rescue Exception => ex
50
+ job_error("Exception!", job, ex)
51
+ raise ex
52
+ end
53
+
54
+ def acquire(time_now)
55
+ logger.debug "SayWhen:: Looking for job that should be ready to fire before #{time_now}"
56
+ if job = self.storage.acquire_next(time_now)
57
+ logger.debug "SayWhen:: got a job: #{job.inspect}"
58
+ else
59
+ logger.debug "SayWhen:: no jobs to acquire"
60
+ end
61
+ job
62
+ end
63
+
64
+ def process(job, time_now)
65
+ # delegate processing the trigger to the processor
66
+ processor.process(job)
67
+ logger.debug "SayWhen:: job processed: #{job.inspect}"
68
+
69
+ # this should update next fire at, and put back in list of scheduled jobs
70
+ storage.fired(job, time_now)
71
+ logger.debug "SayWhen:: job fired: #{job.inspect}"
72
+ end
73
+
74
+ def release(job)
75
+ logger.info "SayWhen::Scheduler release: #{job.inspect}"
76
+ job.release if job
77
+ end
78
+
79
+ def tick(t = tick_length)
80
+ sleep(t.to_f)
81
+ end
82
+
83
+ def tick_length
84
+ @tick_length ||= SayWhen.options[:tick_length].to_f
85
+ end
86
+
87
+ def error_tick_length
88
+ @error_tick_length ||= SayWhen.options[:error_tick_length].to_f || tick_length
89
+ end
90
+
91
+ def reset_acquired_length
92
+ @reset_acquired_length ||= SayWhen.options[:reset_acquired_length].to_f
93
+ end
94
+
95
+ def processor
96
+ @processor ||= load_strategy(:processor, SayWhen.options[:processor_strategy])
97
+ end
98
+
99
+ def storage
100
+ @storage ||= load_strategy(:storage, SayWhen.options[:storage_strategy])
101
+ end
102
+
103
+ def logger
104
+ SayWhen.logger
105
+ end
106
+ end
107
+ end
108
+ end