clockwork 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fae14bd8566db2cb7c3be8c5c9625b01dc66ae00
4
- data.tar.gz: ecbed0c0a9cf6017a0e62f62da9cfb67112624da
3
+ metadata.gz: bb04c64391be1de07e805c05256430c06c1d0da6
4
+ data.tar.gz: 3804849a9e343ce52d62609390da392ccb2c6274
5
5
  SHA512:
6
- metadata.gz: c75686b464777f74d87ca6b15d3ac1d57ee83f190e22d32c6b585fecb86c5192575f90d6151588e9454f7d3f8054bd1c63f3fa4d6a3a067f1d93bbd10a14fe4a
7
- data.tar.gz: c68c69e967a99422394197ed570c2c0ce0968e73a7495ec44a55158b99a6c6450a84fd3160d4707d95c5385ddc00b584f4fb350a6b0566b44222f8201215c504
6
+ metadata.gz: d3adf3511969f14520a4d3273dbf3555d690a8a2cb467e217825ce66f8cae9d8cae3c1431f31784ff987061c6acff1c8e081b91bebac858e96ac8013d071a67d
7
+ data.tar.gz: 06a2920e423ecf3f656b2b5f10ad5a8a32cf5bff46a55a12416b94f77bd484b3bf443a3cfdde7267e89a011cc282ef2580ae883191b167918f23cc6e9383c833
data/README.md CHANGED
@@ -136,7 +136,7 @@ module Clockwork
136
136
  end
137
137
  ```
138
138
 
139
- This tells clockwork to fetch all MyScheduledTask instances from the database, and create an event for each, configured based on the instances' `frequency`, `name`, and `at` methods. It also says to reload the tasks from the database every 1.minute - we need to frequently do this as they could have changed (but you can choose a sensible reload frequency by changing the `every:` option). Note that the database sync event will always run on the minute-boundary (i.e. HH:MM::00), and that events which have been synced from the database won't be run in that same clock cycle (this prevents a task from the database being run twice).
139
+ This tells clockwork to fetch all MyScheduledTask instances from the database, and create an event for each, configured based on the instances' `frequency`, `name`, and `at` methods. It also says to reload the tasks from the database every 1.minute - we need to frequently do this as they could have changed (but you can choose a sensible reload frequency by changing the `every:` option).
140
140
 
141
141
  Rails ActiveRecord models are a perfect candidate for the model class, but you could use something else. The only requirements are:
142
142
 
@@ -144,7 +144,7 @@ Rails ActiveRecord models are a perfect candidate for the model class, but you c
144
144
  2. the instances returned respond to:
145
145
  `frequency` returning the how frequently (in seconds) the database task should be run
146
146
  `name` returning the task's job name (this is what gets passed into the block above)
147
- `at` return nil or '' if not using :at, or any acceptable clockwork :at string
147
+ `at` return nil or `''` if not using `:at`, or otherwise any acceptable clockwork `:at` string
148
148
 
149
149
  Here's an example of one way of setting up your ActiveRecord models, using Sidekiq for background tasks, and making the model class a worker:
150
150
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "clockwork"
3
- s.version = "0.7.3"
3
+ s.version = "0.7.4"
4
4
 
5
5
  s.authors = ["Adam Wiggins", "tomykaira"]
6
6
  s.license = 'MIT'
@@ -8,14 +8,71 @@ module Clockwork
8
8
 
9
9
  extend Methods
10
10
 
11
- class ManagerWithDatabaseTasks < Manager
11
+ class DatabaseEventSyncPerformer
12
+
13
+ def initialize(manager, model, proc)
14
+ @manager = manager
15
+ @model = model
16
+ @block = proc
17
+ @events = {}
18
+ end
19
+
20
+ # Ensure clockwork events reflect database tasks
21
+ # Adds any new tasks, modifies updated ones, and delets removed ones
22
+ def sync
23
+ model_ids_that_exist = []
24
+
25
+ @model.all.each do |db_task|
26
+ model_ids_that_exist << db_task.id
27
+
28
+ if !event_exists_for_task(db_task) || db_task_has_changed(db_task)
29
+ create_event_for_database_task(db_task)
30
+ end
31
+ end
32
+
33
+ remove_deleted_database_tasks(model_ids_that_exist)
34
+ end
35
+
36
+ def events
37
+ @events.values
38
+ end
12
39
 
13
- SECOND_TO_RUN_DATABASE_SYNC_AT = 0
40
+ def add_event(e, task_id)
41
+ @events[task_id] = e
42
+ end
43
+
44
+ protected
45
+
46
+ def create_event_for_database_task(db_task)
47
+ options = {
48
+ :from_database => true,
49
+ :db_task_id => db_task.id,
50
+ :performer => self,
51
+ :at => db_task.at.blank? ? nil : db_task.at.split(',')
52
+ }
53
+
54
+ @manager.every db_task.frequency, db_task.name, options, &@block
55
+ end
56
+
57
+ def event_exists_for_task(db_task)
58
+ @events[db_task.id]
59
+ end
60
+
61
+ def remove_deleted_database_tasks(model_ids_that_exist)
62
+ @events.reject!{|db_task_id, _| !model_ids_that_exist.include?(db_task_id) }
63
+ end
64
+
65
+ def db_task_has_changed(task)
66
+ event = @events[task.id]
67
+ task.name != event.job || task.frequency != event.instance_variable_get(:@period)
68
+ end
69
+ end
70
+
71
+ class ManagerWithDatabaseTasks < Manager
14
72
 
15
73
  def initialize
16
74
  super
17
- @events_from_database = []
18
- @next_sync_database_tasks_identifier = 0
75
+ @database_event_sync_performers = []
19
76
  end
20
77
 
21
78
  def sync_database_tasks(options={}, &block)
@@ -24,64 +81,33 @@ module Clockwork
24
81
  end
25
82
  raise ArgumentError.new(":every must be greater or equal to 1.minute") if options[:every] < 1.minute
26
83
 
27
- model = options[:model]
28
- frequency = options[:every]
29
- sync_task_id = get_sync_task_id
30
-
31
- # Prevent database tasks from running in same cycle as the database sync,
32
- # as this can lead to the same task being run twice
33
- options_to_run_database_sync_in_own_cycle = { :if => lambda { |t| t.sec == SECOND_TO_RUN_DATABASE_SYNC_AT } }
84
+ sync_performer = DatabaseEventSyncPerformer.new(self, options[:model], block)
85
+ @database_event_sync_performers << sync_performer
34
86
 
35
87
  # create event that syncs clockwork events with database events
36
- every frequency, "sync_database_tasks_for_model_#{model}", options_to_run_database_sync_in_own_cycle do
37
- reload_events_from_database sync_task_id, model, &block
88
+ every options[:every], "sync_database_tasks_for_model_#{options[:model]}" do
89
+ sync_performer.sync
38
90
  end
39
91
  end
40
92
 
93
+ private
41
94
 
42
- protected
43
-
44
- # sync_task_id's are used to group the database events from a particular sync_database_tasks call
45
- # This method hands out the ids, incrementing the id to keep them unique.
46
- def get_sync_task_id
47
- current_sync_task_id = @next_sync_database_tasks_identifier
48
- @next_sync_database_tasks_identifier += 1
49
- current_sync_task_id
50
- end
51
-
52
- def reload_events_from_database(sync_task_id, model, &block)
53
- @events_from_database[sync_task_id] = []
54
-
55
- model.all.each do |db_task|
56
- options = { from_database: true, :sync_task_id => sync_task_id }
57
- options[:at] = db_task.at.split(',') unless db_task.at.blank?
58
-
59
- # If database tasks can be scheduled in same clock cycle that database syncs occur
60
- # then previous copy of database sync task will be stored and set to run (in #tick events variable)
61
- # *before* we then delete all database tasks. This causes the task to be run at HH:00 (previous copy)
62
- # and at HH:01 (newly fetched copy).
63
- option_to_prevent_database_tasks_running_in_same_cycle_as_sync = { :if => lambda{|t| t.sec != SECOND_TO_RUN_DATABASE_SYNC_AT } }
64
- every db_task.frequency,
65
- db_task.name,
66
- options.merge(option_to_prevent_database_tasks_running_in_same_cycle_as_sync),
67
- &block
68
- end
95
+ def events_from_database_as_array
96
+ @database_event_sync_performers.collect{|performer| performer.events}.flatten
69
97
  end
70
98
 
71
- private
72
-
73
99
  def events_to_run(t)
74
- (@events + @events_from_database.flatten).select{|event| event.run_now?(t) }
100
+ (@events + events_from_database_as_array).select{|event| event.run_now?(t) }
75
101
  end
76
102
 
77
103
  def register(period, job, block, options)
78
- event = Event.new(self, period, job, block || handler, options)
79
- if options[:from_database]
80
- @events_from_database[options[:sync_task_id]] << event
81
- else
82
- @events << event
104
+ Event.new(self, period, job, block || handler, options).tap do |e|
105
+ if options[:from_database]
106
+ options[:performer].add_event(e, options[:db_task_id])
107
+ else
108
+ @events << e
109
+ end
83
110
  end
84
- event
85
111
  end
86
112
  end
87
113
  end
@@ -56,135 +56,160 @@ class ManagerWithDatabaseTasksTest < Test::Unit::TestCase
56
56
  end
57
57
  end
58
58
 
59
- setup do
60
- @tasks_run = []
61
- @scheduled_task1 = stub(:frequency => 10, :name => 'ScheduledTask:1', :at => nil)
62
- @scheduled_task2 = stub(:frequency => 10, :name => 'ScheduledTask:2', :at => nil)
63
- @scheduled_task1_modified = stub(:frequency => 5, :name => 'ScheduledTaskModified:1', :at => nil)
64
- ScheduledTask.stubs(:all).returns([@scheduled_task1])
59
+ context "when database reload frequency is greater than task frequency period" do
60
+ setup do
61
+ @tasks_run = []
62
+ @scheduled_task1 = stub(:frequency => 10, :name => 'ScheduledTask:1', :at => nil, :id => 1)
63
+ @scheduled_task2 = stub(:frequency => 10, :name => 'ScheduledTask:2', :at => nil, :id => 2)
64
+ @scheduled_task1_modified = stub(:frequency => 5, :name => 'ScheduledTaskModified:1', :at => nil, :id => 3)
65
+ ScheduledTask.stubs(:all).returns([@scheduled_task1])
65
66
 
66
- @database_reload_frequency = 1.minute
67
+ @database_reload_frequency = 1.minute
67
68
 
68
- @now = Time.now
69
- @next_minute = next_minute(@now) # database sync task only happens on minute boundary
69
+ @now = Time.now
70
70
 
71
- # setup the database sync
72
- @manager.sync_database_tasks model: ScheduledTask, every: @database_reload_frequency do |job_name|
73
- @tasks_run << job_name
71
+ # setup the database sync
72
+ @manager.sync_database_tasks model: ScheduledTask, every: @database_reload_frequency do |job_name|
73
+ @tasks_run << job_name
74
+ end
74
75
  end
75
- end
76
76
 
77
- def test_does_not_fetch_database_tasks_until_next_minute
78
- seconds_upto_and_including_next_minute = (@next_minute - @now).seconds.to_i + 1
79
- tick_at(@now, :and_every_second_for => seconds_upto_and_including_next_minute)
80
- assert_equal [], @tasks_run
81
- end
77
+ def test_fetches_and_registers_database_task
78
+ tick_at(@now, :and_every_second_for => 1.second)
79
+ assert_equal ["ScheduledTask:1"], @tasks_run
80
+ end
82
81
 
83
- def test_fetches_and_registers_database_task
84
- tick_at(@next_minute, :and_every_second_for => 1.second)
85
- assert_equal ["ScheduledTask:1"], @tasks_run
86
- end
82
+ def test_multiple_database_tasks_can_be_registered
83
+ ScheduledTask.stubs(:all).returns([@scheduled_task1, @scheduled_task2])
84
+ tick_at(@now, :and_every_second_for => 1.second)
85
+ assert_equal ["ScheduledTask:1", "ScheduledTask:2"], @tasks_run
86
+ end
87
87
 
88
- def test_multiple_database_tasks_can_be_registered
89
- ScheduledTask.stubs(:all).returns([@scheduled_task1, @scheduled_task2])
90
- tick_at(@next_minute, :and_every_second_for => 1.second)
91
- assert_equal ["ScheduledTask:1", "ScheduledTask:2"], @tasks_run
92
- end
88
+ def test_database_task_does_not_run_again_before_frequency_specified_in_database
89
+ tick_at(@now, :and_every_second_for => @scheduled_task1.frequency - 1.second) # runs at 1
90
+ assert_equal 1, @tasks_run.length
91
+ end
93
92
 
94
- def test_database_task_does_not_run_again_before_frequency_specified_in_database
95
- tick_at(@next_minute, :and_every_second_for => 9.seconds) # runs at 1
96
- assert_equal 1, @tasks_run.length
97
- end
93
+ def test_database_task_runs_repeatedly_with_frequency_specified_in_database
94
+ tick_at(@now, :and_every_second_for => (2 * @scheduled_task1.frequency) + 1.second) # runs at 1, 11, and 21
95
+ assert_equal 3, @tasks_run.length
96
+ end
98
97
 
99
- def test_database_task_runs_repeatedly_with_frequency_specified_in_database
100
- tick_at(@next_minute, :and_every_second_for => 21.seconds) # runs at 1, 11, and 21
101
- assert_equal 3, @tasks_run.length
102
- end
98
+ def test_reloads_tasks_from_database
99
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
100
+ tick_at(@now, :and_every_second_for => @database_reload_frequency.seconds)
101
+ @manager.tick # @scheduled_task2 should run immediately on next tick (then every 10 seconds)
102
+
103
+ assert_equal [
104
+ "ScheduledTask:1",
105
+ "ScheduledTask:1",
106
+ "ScheduledTask:1",
107
+ "ScheduledTask:1",
108
+ "ScheduledTask:1",
109
+ "ScheduledTask:1",
110
+ "ScheduledTask:2"], @tasks_run
111
+ end
103
112
 
104
- def test_reloads_tasks_from_database
105
- ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
106
- tick_at(@next_minute, :and_every_second_for => @database_reload_frequency.seconds)
107
- @manager.tick # @scheduled_task2 should run immediately on next tick (then every 10 seconds)
113
+ def test_reloaded_tasks_run_repeatedly
114
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
115
+ tick_at(@now, :and_every_second_for => @database_reload_frequency.seconds + 11.seconds)
116
+ assert_equal ["ScheduledTask:2", "ScheduledTask:2"], @tasks_run[-2..-1]
117
+ end
108
118
 
109
- assert_equal "ScheduledTask:2", @tasks_run.last
110
- end
119
+ def test_reloading_task_with_modified_frequency_will_run_with_new_frequency
120
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task1_modified])
111
121
 
112
- def test_reloaded_tasks_run_repeatedly
113
- ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
114
- tick_at(@next_minute, :and_every_second_for => @database_reload_frequency.seconds + 11.seconds)
115
- assert_equal ["ScheduledTask:2", "ScheduledTask:2"], @tasks_run[-2..-1]
116
- end
122
+ tick_at(@now, :and_every_second_for => 66.seconds)
117
123
 
118
- def test_stops_running_deleted_database_task
119
- ScheduledTask.stubs(:all).returns([@scheduled_task1], [])
120
- tick_at(@next_minute, :and_every_second_for => @database_reload_frequency.seconds)
121
- before = @tasks_run.dup
124
+ # task1 runs at: 1, 11, 21, 31, 41, 51 (6 runs)
125
+ # database tasks are reloaded at: 60
126
+ # task1_modified runs at: 61 (next tick after reload) and then 66 (2 runs)
127
+ assert_equal 8, @tasks_run.length
128
+ end
122
129
 
123
- # tick through reload, and run for enough ticks that previous task would have run
124
- tick_at(@next_minute + @database_reload_frequency.seconds + 20.seconds)
125
- after = @tasks_run
130
+ def test_stops_running_deleted_database_task
131
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [])
132
+ tick_at(@now, :and_every_second_for => @database_reload_frequency.seconds)
133
+ before = @tasks_run.dup
126
134
 
127
- assert_equal before, after
128
- end
135
+ # tick through reload, and run for enough ticks that previous task would have run
136
+ tick_at(@now + @database_reload_frequency.seconds + 20.seconds)
137
+ after = @tasks_run
129
138
 
130
- def test_reloading_task_with_modified_frequency_will_run_with_new_frequency
131
- ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task1_modified])
139
+ assert_equal before, after
140
+ end
132
141
 
133
- tick_at(@next_minute, :and_every_second_for => 66.seconds)
142
+ def test_edited_tasks_switch_to_new_settings
143
+ tick_at @now, :and_every_second_for => @database_reload_frequency.seconds - 1.second
144
+ modified_task_1 = stub(:frequency => 30, :name => 'ScheduledTask:1_modified', :at => nil, :id => 1)
145
+ ScheduledTask.stubs(:all).returns([modified_task_1])
146
+ tick_at @now + @database_reload_frequency.seconds, :and_every_second_for => @database_reload_frequency.seconds - 1.seconds
147
+ assert_equal [
148
+ "ScheduledTask:1",
149
+ "ScheduledTask:1",
150
+ "ScheduledTask:1",
151
+ "ScheduledTask:1",
152
+ "ScheduledTask:1",
153
+ "ScheduledTask:1",
154
+ "ScheduledTask:1_modified",
155
+ "ScheduledTask:1_modified"
156
+ ], @tasks_run
157
+ end
134
158
 
135
- # task1 runs at: 1, 11, 21, 31, 41, 51 (6 runs)
136
- # database tasks are reloaded at: 60
137
- # task1_modified runs at: 61 (next tick after reload) and then 66 (2 runs)
138
- assert_equal 8, @tasks_run.length
139
- end
159
+ def test_daily_task_with_at_should_only_run_once
160
+ next_minute = next_minute(@now)
161
+ at = next_minute.strftime('%H:%M')
162
+ @scheduled_task_with_at = stub(:frequency => 1.day, :name => 'ScheduledTaskWithAt:1', :at => at, :id => 5)
163
+ ScheduledTask.stubs(:all).returns([@scheduled_task_with_at])
140
164
 
141
- # Catch a bug caused by allowing database tasks to be run in the same clock cycle that the database
142
- # sync occurs. When this happens, a previously scheduled database task will be scheduled to run,
143
- # we then fetch the same task afresh (wiping out the @events_from_database object), but the
144
- # previously scheduled task still runs because #task `events` variable already stored it *before*
145
- # we wiped out the @events_from_database objects.
146
- #
147
- # We have a situation like this:
148
- #
149
- # 12:31:00 #tick loops through events to run
150
- # sync_database_tasks_for_model_ task is run
151
- # fetches database task 1 with :at => 12:32, and schedules it to run (object task 1')
152
- #
153
- # ...
154
- #
155
- # 12:32:00 #tick loops through events that should be run, of which task 1' is included
156
- # sync_database_tasks_for_model_ task is run
157
- # fetches database task 1 with :at => 12:32, and schedules it to run (object task 1'')
158
- # task 1' is run
159
- #
160
- # 12:32:01 #tick loops through events that should be run, of which task 1'' is included
161
- # task 1'' is run
162
- def test_daily_task_with_at_should_not_run_twice_when_already_scheduled
163
- minute_after_next = next_minute(@next_minute)
164
- at = minute_after_next.strftime('%H:%M')
165
- @scheduled_task_with_at = stub(:frequency => 1.day, :name => 'ScheduledTaskWithAt:1', :at => at)
166
- ScheduledTask.stubs(:all).returns([@scheduled_task_with_at])
167
-
168
- # tick from now, though specified :at time
169
- tick_at(@now, :and_every_second_for => (2 * @database_reload_frequency.seconds) + 1.second)
170
-
171
- assert_equal 1, @tasks_run.length
172
- end
165
+ # tick from now, though specified :at time
166
+ tick_at(@now, :and_every_second_for => (2 * @database_reload_frequency.seconds) + 1.second)
167
+
168
+ assert_equal 1, @tasks_run.length
169
+ end
170
+
171
+ def test_having_multiple_sync_database_tasks_will_work
172
+ ScheduledTask.stubs(:all).returns([@scheduled_task1])
173
+
174
+ # setup 2nd database sync
175
+ @scheduled_task_type2 = stub(:frequency => 10, :name => 'ScheduledTaskType2:1', :at => nil, :id => 6)
173
176
 
174
- def test_having_multiple_sync_database_tasks_will_work
175
- ScheduledTask.stubs(:all).returns([@scheduled_task1])
177
+ ScheduledTaskType2.stubs(:all).returns([@scheduled_task_type2])
178
+ @manager.sync_database_tasks model: ScheduledTaskType2, every: @database_reload_frequency do |job_name|
179
+ @tasks_run << job_name
180
+ end
176
181
 
177
- # setup 2nd database sync
178
- @scheduled_task_type2 = stub(:frequency => 10, :name => 'ScheduledTaskType2:1', :at => nil)
182
+ tick_at(@now, :and_every_second_for => 1.second)
179
183
 
180
- ScheduledTaskType2.stubs(:all).returns([@scheduled_task_type2])
181
- @manager.sync_database_tasks model: ScheduledTaskType2, every: @database_reload_frequency do |job_name|
182
- @tasks_run << job_name
184
+ assert_equal ["ScheduledTask:1", "ScheduledTaskType2:1"], @tasks_run
183
185
  end
186
+ end
187
+
188
+ context "when database reload frequency is less than task frequency period" do
189
+ setup do
190
+ @tasks_run = []
191
+ @scheduled_task1 = stub(:frequency => 5.minutes, :name => 'ScheduledTask:1', :at => nil, :id => 1)
192
+ @scheduled_task2 = stub(:frequency => 10, :name => 'ScheduledTask:2', :at => nil, :id => 2)
193
+ @scheduled_task1_modified = stub(:frequency => 5, :name => 'ScheduledTaskModified:1', :at => nil)
194
+ ScheduledTask.stubs(:all).returns([@scheduled_task1])
195
+
196
+ @database_reload_frequency = 1.minute
184
197
 
185
- tick_at(@next_minute, :and_every_second_for => 1.second)
198
+ @now = Time.now
199
+ @next_minute = next_minute(@now) # database sync task only happens on minute boundary
186
200
 
187
- assert_equal ["ScheduledTask:1", "ScheduledTaskType2:1"], @tasks_run
201
+ # setup the database sync
202
+ @manager.sync_database_tasks model: ScheduledTask, every: @database_reload_frequency do |job_name|
203
+ @tasks_run << job_name
204
+ end
205
+ end
206
+
207
+ # For example: if the manager updates every minute, but the task specifies 5 minutes,
208
+ # the task will still run every minute.
209
+ def test_it_only_runs_the_task_once_within_the_task_frequency_period
210
+ tick_at(@now, :and_every_second_for => 5.minutes)
211
+ assert_equal 1, @tasks_run.length
212
+ end
188
213
  end
189
214
  end
190
215
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clockwork
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Wiggins
@@ -9,104 +9,104 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-20 00:00:00.000000000 Z
12
+ date: 2014-04-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tzinfo
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - '>='
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - '>='
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: activesupport
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - '>='
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - '>='
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: bundler
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ~>
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
48
  version: '1.3'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ~>
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '1.3'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rake
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - '>='
60
+ - - ">="
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - '>='
67
+ - - ">="
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: daemons
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - '>='
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - '>='
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: contest
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - '>='
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - '>='
95
+ - - ">="
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: mocha
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - '>='
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
104
  version: '0'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - '>='
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
112
  description: A scheduler process to replace cron, using a more flexible Ruby syntax
@@ -121,8 +121,8 @@ extensions: []
121
121
  extra_rdoc_files:
122
122
  - README.md
123
123
  files:
124
- - .gitignore
125
- - .travis.yml
124
+ - ".gitignore"
125
+ - ".travis.yml"
126
126
  - Gemfile
127
127
  - README.md
128
128
  - Rakefile
@@ -152,17 +152,17 @@ require_paths:
152
152
  - lib
153
153
  required_ruby_version: !ruby/object:Gem::Requirement
154
154
  requirements:
155
- - - '>='
155
+ - - ">="
156
156
  - !ruby/object:Gem::Version
157
157
  version: '0'
158
158
  required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  requirements:
160
- - - '>='
160
+ - - ">="
161
161
  - !ruby/object:Gem::Version
162
162
  version: '0'
163
163
  requirements: []
164
164
  rubyforge_project:
165
- rubygems_version: 2.0.3
165
+ rubygems_version: 2.2.0
166
166
  signing_key:
167
167
  specification_version: 4
168
168
  summary: A scheduler process to replace cron.