say_when 0.4.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +13 -4
- data/Gemfile +1 -9
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/Rakefile +6 -6
- data/lib/generators/say_when/migration/migration_generator.rb +8 -5
- data/lib/generators/say_when/migration/templates/migration.rb +8 -7
- data/lib/say_when/base_job.rb +2 -0
- data/lib/say_when/cron_expression.rb +129 -191
- data/lib/say_when/processor/active_messaging.rb +7 -8
- data/lib/say_when/processor/base.rb +5 -3
- data/lib/say_when/processor/shoryuken.rb +14 -0
- data/lib/say_when/processor/simple.rb +2 -0
- data/lib/say_when/railtie.rb +9 -0
- data/lib/say_when/scheduler.rb +49 -90
- data/lib/say_when/storage/active_record/acts.rb +16 -16
- data/lib/say_when/storage/active_record/job.rb +17 -24
- data/lib/say_when/storage/active_record/job_execution.rb +5 -8
- data/lib/say_when/storage/memory/base.rb +3 -1
- data/lib/say_when/storage/memory/job.rb +14 -42
- data/lib/say_when/tasks.rb +4 -4
- data/lib/say_when/triggers/base.rb +4 -3
- data/lib/say_when/triggers/cron_strategy.rb +4 -3
- data/lib/say_when/triggers/instance_strategy.rb +4 -3
- data/lib/say_when/triggers/once_strategy.rb +3 -2
- data/lib/say_when/version.rb +3 -1
- data/lib/say_when.rb +8 -7
- data/lib/tasks/say_when.rake +3 -1
- data/say_when.gemspec +26 -19
- data/test/active_record_helper.rb +13 -0
- data/{spec → test}/db/schema.rb +4 -4
- data/{spec/spec_helper.rb → test/minitest_helper.rb} +9 -19
- data/test/say_when/cron_expression_spec.rb +74 -0
- data/{spec/say_when/processor/active_messaging_spec.rb → test/say_when/processor/active_messaging_test.rb} +17 -13
- data/test/say_when/scheduler_test.rb +75 -0
- data/test/say_when/storage/active_record/job_test.rb +90 -0
- data/test/say_when/storage/memory/job_test.rb +32 -0
- data/test/say_when/storage/memory/trigger_test.rb +54 -0
- data/test/say_when/triggers/once_strategy_test.rb +23 -0
- data/{spec → test}/support/models.rb +5 -3
- metadata +97 -54
- data/.travis.yml +0 -4
- data/generators/say_when_migration/say_when_migration_generator.rb +0 -11
- data/generators/say_when_migration/templates/migration.rb +0 -48
- data/spec/active_record_spec_helper.rb +0 -9
- data/spec/say_when/cron_expression_spec.rb +0 -72
- data/spec/say_when/scheduler_spec.rb +0 -126
- data/spec/say_when/storage/active_record/job_spec.rb +0 -97
- data/spec/say_when/storage/memory/job_spec.rb +0 -45
- data/spec/say_when/storage/memory/trigger_spec.rb +0 -54
- data/spec/say_when/triggers/once_strategy_spec.rb +0 -22
- data/spec/spec.opts +0 -4
@@ -1,22 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'activemessaging/message_sender'
|
2
4
|
|
3
5
|
module SayWhen
|
4
6
|
module Processor
|
5
|
-
|
6
7
|
class ActiveMessaging < SayWhen::Processor::Base
|
7
|
-
|
8
|
+
|
8
9
|
include ::ActiveMessaging::MessageSender
|
9
|
-
|
10
|
+
|
10
11
|
def initialize(scheduler)
|
11
12
|
super(scheduler)
|
12
13
|
end
|
13
14
|
|
14
15
|
# send the job to the other end, then in the a13g processor, call the execute method
|
15
16
|
def process(job)
|
16
|
-
publish(:say_when, {:
|
17
|
+
publish(:say_when, { job_id: job.id }.to_yaml )
|
17
18
|
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
19
|
+
end if defined?(::ActiveMessaging)
|
21
20
|
end
|
22
|
-
end
|
21
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module SayWhen
|
2
4
|
module Processor
|
3
|
-
|
5
|
+
|
4
6
|
class Base
|
5
7
|
attr_accessor :scheduler
|
6
|
-
|
8
|
+
|
7
9
|
def initialize(scheduler)
|
8
10
|
@scheduler = scheduler
|
9
11
|
end
|
10
|
-
|
12
|
+
|
11
13
|
def process(job)
|
12
14
|
raise NotImplementedError.new('You need to implement process(job)')
|
13
15
|
end
|
data/lib/say_when/scheduler.rb
CHANGED
@@ -1,50 +1,42 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
|
+
module SayWhen
|
3
4
|
class Scheduler
|
4
5
|
|
5
6
|
DEFAULT_PROCESSOR_CLASS = SayWhen::Processor::Simple
|
6
7
|
DEFAULT_STORAGE_STRATEGY = :memory
|
7
8
|
|
8
9
|
@@scheduler = nil
|
9
|
-
@@lock =
|
10
|
+
@@lock = Mutex.new
|
10
11
|
|
11
|
-
attr_accessor :storage_strategy, :processor_class, :tick_length
|
12
|
+
attr_accessor :storage_strategy, :processor_class, :tick_length
|
12
13
|
|
13
14
|
attr_accessor :running
|
14
15
|
|
15
16
|
# support for a singleton scheduler, but you are not restricted to this
|
16
17
|
class << self
|
17
|
-
|
18
18
|
def scheduler
|
19
|
-
|
20
|
-
|
21
|
-
@@scheduler = self.new
|
22
|
-
end
|
23
|
-
}
|
19
|
+
return @@scheduler if @@scheduler
|
20
|
+
@@lock.synchronize { @@scheduler = self.new if @@scheduler.nil? }
|
24
21
|
@@scheduler
|
25
22
|
end
|
26
23
|
|
27
24
|
def configure
|
28
|
-
yield
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def lock
|
33
|
-
@@lock ||= Mutex.new
|
25
|
+
yield scheduler
|
26
|
+
scheduler
|
34
27
|
end
|
35
28
|
|
36
29
|
def schedule(job)
|
37
|
-
|
30
|
+
scheduler.schedule(job)
|
38
31
|
end
|
39
32
|
|
40
33
|
def start
|
41
|
-
|
34
|
+
scheduler.start
|
42
35
|
end
|
43
36
|
end
|
44
37
|
|
45
38
|
def initialize
|
46
|
-
self.tick_length =
|
47
|
-
self.reset_acquired_length = 3600
|
39
|
+
self.tick_length = [ENV['SAY_WHEN_TICK_LENGTH'].to_i, 5].max
|
48
40
|
end
|
49
41
|
|
50
42
|
def processor
|
@@ -63,88 +55,55 @@ module SayWhen
|
|
63
55
|
trap("TERM", "EXIT")
|
64
56
|
|
65
57
|
begin
|
58
|
+
|
66
59
|
self.running = true
|
67
60
|
|
68
61
|
logger.info "SayWhen::Scheduler running"
|
62
|
+
job = nil
|
69
63
|
while running
|
70
|
-
|
64
|
+
begin
|
65
|
+
time_now = Time.now
|
66
|
+
logger.debug "SayWhen:: Looking for job that should be ready to fire before #{time_now}"
|
67
|
+
job = job_class.acquire_next(time_now)
|
68
|
+
if job.nil?
|
69
|
+
logger.debug "SayWhen:: no jobs to acquire, sleep"
|
70
|
+
sleep(tick_length)
|
71
|
+
else
|
72
|
+
logger.debug "SayWhen:: got a job: #{job.inspect}"
|
73
|
+
# delegate processing the trigger to the processor
|
74
|
+
self.processor.process(job)
|
75
|
+
logger.debug "SayWhen:: job processed"
|
76
|
+
|
77
|
+
# this should update next fire at, and put back in list of scheduled jobs
|
78
|
+
job.fired(time_now)
|
79
|
+
logger.debug "SayWhen:: job fired complete"
|
80
|
+
end
|
81
|
+
rescue StandardError => ex
|
82
|
+
job_msg = job && "job: #{job.inspect} "
|
83
|
+
logger.error "SayWhen:: Failure: #{job_msg}exception: #{ex.message}\n\t#{ex.backtrace.join("\t\n")}"
|
84
|
+
safe_release(job)
|
85
|
+
sleep(tick_length)
|
86
|
+
rescue Interrupt => ex
|
87
|
+
job_msg = job && "\n - interrupted job: #{job.inspect}\n"
|
88
|
+
logger.error "\nSayWhen:: Interrupt! #{ex.inspect}#{job_msg}"
|
89
|
+
safe_release(job)
|
90
|
+
exit
|
91
|
+
rescue Exception => ex
|
92
|
+
job_msg = job && "job: #{job.inspect} "
|
93
|
+
logger.error "SayWhen:: Exception: #{job_msg}exception: #{ex.message}\n\t#{ex.backtrace.join("\t\n")}"
|
94
|
+
safe_release(job)
|
95
|
+
exit
|
96
|
+
end
|
71
97
|
end
|
72
|
-
rescue Exception => ex
|
73
|
-
logger.error "SayWhen::Scheduler stopping, error: #{ex.class.name}: #{ex.message}"
|
74
|
-
exit
|
75
98
|
end
|
76
99
|
|
77
100
|
logger.info "SayWhen::Scheduler stopped"
|
78
101
|
end
|
79
102
|
|
80
|
-
def
|
81
|
-
jobs_processed = 0
|
82
|
-
while(jobs_processed < max_jobs)
|
83
|
-
if job = process_jobs
|
84
|
-
jobs_processed += 1
|
85
|
-
else
|
86
|
-
break
|
87
|
-
end
|
88
|
-
end
|
89
|
-
return jobs_processed
|
90
|
-
end
|
91
|
-
|
92
|
-
def process_jobs
|
93
|
-
job = nil
|
94
|
-
time_now = Time.now
|
95
|
-
self.reset_next_at ||= Time.now
|
96
|
-
|
97
|
-
if reset_acquired_length > 0 && reset_next_at <= time_now
|
98
|
-
self.reset_next_at = time_now + reset_acquired_length
|
99
|
-
logger.debug "SayWhen:: reset acquired at #{time_now}, try again at #{reset_next_at}"
|
100
|
-
job_class.reset_acquired(reset_acquired_length)
|
101
|
-
end
|
102
|
-
|
103
|
-
begin
|
104
|
-
logger.debug "SayWhen:: Looking for job that should be ready to fire before #{time_now}"
|
105
|
-
job = job_class.acquire_next(time_now)
|
106
|
-
rescue StandardError => ex
|
107
|
-
job_error("Failure to acquire job", job, ex)
|
108
|
-
job = nil
|
109
|
-
end
|
110
|
-
|
111
|
-
if job.nil?
|
112
|
-
logger.debug "SayWhen:: no jobs to acquire, sleep"
|
113
|
-
sleep(tick_length)
|
114
|
-
return job
|
115
|
-
end
|
116
|
-
|
117
|
-
begin
|
118
|
-
logger.debug "SayWhen:: got a job: #{job.inspect}"
|
119
|
-
# delegate processing the trigger to the processor
|
120
|
-
self.processor.process(job)
|
121
|
-
logger.debug "SayWhen:: job processed"
|
122
|
-
|
123
|
-
# if successful, update next fire at, put back to waiting / ended
|
124
|
-
job.fired(time_now)
|
125
|
-
logger.debug "SayWhen:: job fired complete"
|
126
|
-
rescue StandardError => ex
|
127
|
-
job_error("Failure to process", job, ex)
|
128
|
-
end
|
129
|
-
|
130
|
-
return job
|
131
|
-
|
132
|
-
rescue StandardError => ex
|
133
|
-
job_error("Error!", job, ex)
|
134
|
-
sleep(tick_length)
|
135
|
-
return job
|
136
|
-
rescue Interrupt => ex
|
137
|
-
job_error("Interrupt!", job, ex)
|
138
|
-
raise ex
|
139
|
-
rescue Exception => ex
|
140
|
-
job_error("Exception!", job, ex)
|
141
|
-
raise ex
|
142
|
-
end
|
143
|
-
|
144
|
-
def job_error(msg, job, ex)
|
145
|
-
job_msg = job && " job:'#{job.inspect}'"
|
146
|
-
logger.error "SayWhen::Scheduler #{msg}#{job_msg}: #{ex.message}\n\t#{ex.backtrace.join("\t\n")}"
|
103
|
+
def safe_release(job)
|
147
104
|
job.release if job
|
105
|
+
rescue
|
106
|
+
logger "Failed to release job: #{job.inspect}" rescue nil
|
148
107
|
end
|
149
108
|
|
150
109
|
def stop
|
@@ -1,57 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module SayWhen #:nodoc:
|
2
4
|
module Storage #:nodoc:
|
3
5
|
module ActiveRecord #:nodoc:
|
4
6
|
module Acts #:nodoc:
|
5
7
|
|
6
|
-
|
7
|
-
base.extend ClassMethods
|
8
|
-
end
|
8
|
+
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
def acts_as_scheduled
|
12
12
|
include SayWhen::Storage::ActiveRecord::Acts::InstanceMethods
|
13
|
-
|
14
|
-
has_many :scheduled_jobs, :
|
13
|
+
|
14
|
+
has_many :scheduled_jobs, as: :scheduled, class_name: 'SayWhen::Storage::ActiveRecord::Job', dependent: :destroy
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
module InstanceMethods
|
19
19
|
|
20
20
|
def schedule_instance(next_at_method, job={})
|
21
21
|
options = job_options(job)
|
22
22
|
options[:trigger_strategy] = 'instance'
|
23
|
-
options[:trigger_options] = {:next_at_method
|
23
|
+
options[:trigger_options] = { next_at_method: next_at_method }
|
24
24
|
Scheduler.schedule(options)
|
25
25
|
end
|
26
26
|
|
27
27
|
def schedule_cron(expression, time_zone, job={})
|
28
28
|
options = job_options(job)
|
29
29
|
options[:trigger_strategy] = 'cron'
|
30
|
-
options[:trigger_options] = {:
|
30
|
+
options[:trigger_options] = { expression: expression, time_zone: time_zone }
|
31
31
|
Scheduler.schedule(options)
|
32
32
|
end
|
33
33
|
|
34
34
|
def schedule_once(time, job={})
|
35
35
|
options = job_options(job)
|
36
36
|
options[:trigger_strategy] = 'once'
|
37
|
-
options[:trigger_options] = {:
|
37
|
+
options[:trigger_options] = { at: time}
|
38
38
|
Scheduler.schedule(options)
|
39
39
|
end
|
40
40
|
|
41
41
|
def schedule_in(after, job={})
|
42
42
|
options = job_options(job)
|
43
43
|
options[:trigger_strategy] = 'once'
|
44
|
-
options[:trigger_options] = {:
|
44
|
+
options[:trigger_options] = { at: (Time.now + after)}
|
45
45
|
Scheduler.schedule(options)
|
46
46
|
end
|
47
47
|
|
48
48
|
# helpers
|
49
49
|
|
50
50
|
def job_options(job)
|
51
|
-
{
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
51
|
+
{
|
52
|
+
scheduled: self,
|
53
|
+
job_class: extract_job_class(job),
|
54
|
+
job_method: extract_job_method(job),
|
55
|
+
data: extract_data(job)
|
56
|
+
}
|
55
57
|
end
|
56
58
|
|
57
59
|
def extract_job_class(job)
|
@@ -81,9 +83,7 @@ module SayWhen #:nodoc:
|
|
81
83
|
nil
|
82
84
|
end
|
83
85
|
end
|
84
|
-
|
85
86
|
end # InstanceMethods
|
86
|
-
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
require 'say_when/base_job'
|
3
5
|
require 'say_when/storage/active_record/job_execution'
|
@@ -8,41 +10,34 @@ module SayWhen
|
|
8
10
|
module ActiveRecord
|
9
11
|
|
10
12
|
class Job < ::ActiveRecord::Base
|
13
|
+
|
11
14
|
include SayWhen::BaseJob
|
12
|
-
|
15
|
+
|
16
|
+
self.table_name = 'say_when_jobs'
|
17
|
+
|
13
18
|
serialize :trigger_options
|
14
19
|
serialize :data
|
15
|
-
belongs_to :scheduled, :polymorphic => true
|
16
|
-
has_many :job_executions, :class_name=>'SayWhen::Storage::ActiveRecord::JobExecution'
|
17
|
-
before_create :set_defaults
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
"status = '#{STATE_WAITING}'",
|
24
|
-
["status = ? and updated_at < ?", STATE_ACQUIRED, older_than]
|
25
|
-
)
|
26
|
-
end
|
21
|
+
belongs_to :scheduled, polymorphic: true
|
22
|
+
has_many :job_executions, class_name: 'SayWhen::Storage::ActiveRecord::JobExecution'
|
23
|
+
|
24
|
+
before_create :set_defaults
|
27
25
|
|
28
26
|
def self.acquire_next(no_later_than)
|
29
|
-
|
27
|
+
next_job = nil
|
28
|
+
|
30
29
|
hide_logging do
|
31
30
|
SayWhen::Storage::ActiveRecord::Job.transaction do
|
32
31
|
# select and lock the next job that needs executin' (status waiting, and after no_later_than)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
:conditions => ['status = ? and ? >= next_fire_at',
|
37
|
-
STATE_WAITING,
|
38
|
-
no_later_than])
|
32
|
+
next_job = where('status = ? and next_fire_at < ?', STATE_WAITING, no_later_than.in_time_zone('UTC')).
|
33
|
+
order('next_fire_at ASC').
|
34
|
+
lock(true).first
|
39
35
|
|
40
36
|
# set status to acquired to take it out of rotation
|
41
|
-
|
42
|
-
|
37
|
+
next_job.update_attribute(:status, STATE_ACQUIRED) unless next_job.nil?
|
43
38
|
end
|
44
39
|
end
|
45
|
-
|
40
|
+
next_job
|
46
41
|
end
|
47
42
|
|
48
43
|
def set_defaults
|
@@ -99,9 +94,7 @@ module SayWhen
|
|
99
94
|
::ActiveRecord::Base.logger = old_logger
|
100
95
|
end
|
101
96
|
end
|
102
|
-
|
103
97
|
end
|
104
|
-
|
105
98
|
end
|
106
99
|
end
|
107
100
|
end
|
@@ -1,17 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
|
3
5
|
module SayWhen
|
4
6
|
module Storage
|
5
7
|
module ActiveRecord
|
6
|
-
|
7
|
-
class JobExecution < ::ActiveRecord::Base
|
8
|
-
|
8
|
+
class JobExecution < ::ActiveRecord::Base
|
9
9
|
self.table_name = "say_when_job_executions"
|
10
|
-
|
11
|
-
belongs_to :job, :class_name=>'SayWhen::Storage::ActiveRecord::Job'
|
12
|
-
|
10
|
+
belongs_to :job, class_name: 'SayWhen::Storage::ActiveRecord::Job'
|
13
11
|
end
|
14
|
-
|
15
12
|
end
|
16
13
|
end
|
17
|
-
end
|
14
|
+
end
|
@@ -1,81 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'say_when/storage/memory/base'
|
2
4
|
|
3
5
|
module SayWhen
|
4
|
-
module
|
6
|
+
module Storage
|
5
7
|
module Memory
|
6
8
|
|
7
9
|
# define a trigger class
|
8
10
|
class Job
|
9
11
|
|
10
|
-
cattr_accessor :jobs
|
11
|
-
@@jobs = SortedSet.new
|
12
|
-
|
13
12
|
include SayWhen::Storage::Memory::Base
|
14
|
-
|
13
|
+
include SayWhen::BaseJob
|
15
14
|
|
16
15
|
has_properties :group, :name, :status, :start_at, :end_at
|
17
16
|
has_properties :trigger_strategy, :trigger_options, :last_fire_at, :next_fire_at
|
18
17
|
has_properties :job_class, :job_method, :data
|
19
18
|
has_properties :scheduled
|
20
|
-
has_properties :updated_at
|
21
|
-
|
22
|
-
def self.class_lock
|
23
|
-
@@_lock ||= Mutex.new
|
24
|
-
end
|
25
19
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def self.reset_acquired(older_than_seconds)
|
31
|
-
return unless older_than_seconds.to_i > 0
|
32
|
-
older_than = (Time.now - older_than_seconds.to_i)
|
33
|
-
self.class_lock.synchronize {
|
34
|
-
jobs.select do |j|
|
35
|
-
j.status == STATE_ACQUIRED && j.updated_at < older_than
|
36
|
-
end.each{ |j| j.status = STATE_WAITING }
|
37
|
-
}
|
38
|
-
end
|
20
|
+
cattr_accessor :jobs
|
21
|
+
@@jobs = SortedSet.new
|
22
|
+
@@acquire_lock = Mutex.new
|
39
23
|
|
40
24
|
def self.acquire_next(no_later_than)
|
41
|
-
|
25
|
+
@@acquire_lock.synchronize {
|
42
26
|
|
43
27
|
next_job = jobs.detect(nil) do |j|
|
44
28
|
(j.status == STATE_WAITING) && (j.next_fire_at.to_i <= no_later_than.to_i)
|
45
29
|
end
|
46
30
|
|
47
|
-
if next_job
|
48
|
-
next_job.status = STATE_ACQUIRED
|
49
|
-
next_job.updated_at = Time.now
|
50
|
-
end
|
51
|
-
|
31
|
+
next_job.status = STATE_ACQUIRED if next_job
|
52
32
|
next_job
|
53
33
|
}
|
54
34
|
end
|
55
35
|
|
36
|
+
def self.create(job)
|
37
|
+
job = new(job) if job.is_a?(Hash)
|
38
|
+
self.jobs << job
|
39
|
+
end
|
40
|
+
|
56
41
|
def initialize(options={})
|
57
42
|
super
|
58
|
-
self.updated_at = Time.now
|
59
43
|
self.status = STATE_WAITING unless self.status
|
60
44
|
self.next_fire_at = trigger.next_fire_at
|
61
|
-
self.class.jobs << self
|
62
45
|
end
|
63
46
|
|
64
47
|
def <=>(job)
|
65
48
|
self.next_fire_at.to_i <=> job.next_fire_at.to_i
|
66
49
|
end
|
67
|
-
|
68
|
-
def fired(fired_at=Time.now)
|
69
|
-
super
|
70
|
-
self.updated_at = Time.now
|
71
|
-
end
|
72
|
-
|
73
|
-
def release
|
74
|
-
super
|
75
|
-
self.updated_at = Time.now
|
76
|
-
end
|
77
50
|
end
|
78
|
-
|
79
51
|
end
|
80
52
|
end
|
81
53
|
end
|
data/lib/say_when/tasks.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
namespace :say_when do
|
4
|
+
desc 'Start the SayWhen Scheduler'
|
5
|
+
task start: :environment do
|
5
6
|
require 'say_when'
|
6
7
|
SayWhen::Scheduler.start
|
7
8
|
end
|
8
|
-
|
9
9
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module SayWhen
|
2
4
|
module Triggers
|
3
5
|
module Base
|
@@ -5,13 +7,12 @@ module SayWhen
|
|
5
7
|
attr_accessor :job
|
6
8
|
|
7
9
|
def initialize(options={})
|
8
|
-
|
10
|
+
self.job = options.delete(:job)
|
9
11
|
end
|
10
12
|
|
11
13
|
def next_fire_at(time=nil)
|
12
14
|
raise NotImplementedError.new('You need to implement next_fire_at in your strategy')
|
13
15
|
end
|
14
|
-
|
15
16
|
end
|
16
17
|
end
|
17
|
-
end
|
18
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'say_when/triggers/base'
|
2
4
|
require 'say_when/cron_expression'
|
3
5
|
|
@@ -11,13 +13,12 @@ module SayWhen
|
|
11
13
|
|
12
14
|
def initialize(options={})
|
13
15
|
super
|
14
|
-
|
16
|
+
self.cron_expression = SayWhen::CronExpression.new(options)
|
15
17
|
end
|
16
18
|
|
17
19
|
def next_fire_at(time=nil)
|
18
20
|
cron_expression.next_fire_at(time || Time.now)
|
19
21
|
end
|
20
|
-
|
21
22
|
end
|
22
23
|
end
|
23
|
-
end
|
24
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'say_when/triggers/base'
|
2
4
|
|
3
5
|
module SayWhen
|
@@ -10,14 +12,13 @@ module SayWhen
|
|
10
12
|
|
11
13
|
def initialize(options={})
|
12
14
|
super
|
13
|
-
|
14
|
-
|
15
|
+
self.instance = job.scheduled
|
16
|
+
self.next_at_method = options[:next_at_method] || 'next_fire_at'
|
15
17
|
end
|
16
18
|
|
17
19
|
def next_fire_at(time=Time.now)
|
18
20
|
instance.send(next_at_method, time)
|
19
21
|
end
|
20
|
-
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'say_when/triggers/base'
|
2
4
|
|
3
5
|
module SayWhen
|
@@ -10,14 +12,13 @@ module SayWhen
|
|
10
12
|
|
11
13
|
def initialize(options=nil)
|
12
14
|
super
|
13
|
-
|
15
|
+
self.once_at = options[:at] || Time.now
|
14
16
|
end
|
15
17
|
|
16
18
|
def next_fire_at(time=nil)
|
17
19
|
nfa = once_at if (!time || (time <= once_at))
|
18
20
|
return nfa
|
19
21
|
end
|
20
|
-
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
data/lib/say_when/version.rb
CHANGED