delayed_job_recurring 0.3.4 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +48 -2
  3. data/lib/delayed/recurring_job.rb +43 -54
  4. metadata +27 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 290117f54a785d30a82b864887404a17726190ed
4
- data.tar.gz: 81e2bab83a90f6022e9345a27595d0f57c688b1b
2
+ SHA256:
3
+ metadata.gz: d2df13749a11ec5a5a5fef3f60eb7c7a1216e13a6b93a6e084392a30b0fabefd
4
+ data.tar.gz: 98bbe52c01ef1a79e4ce2c512a47d91e4a9380b8d119fc05605e13a27f805425
5
5
  SHA512:
6
- metadata.gz: 195de5c332484916371e1389c485204e98274428cd093423e0b8058823aa6f8067a0f10c1437ff7b79b83b643eb30df27c705bb2ff12e8baadf356f157b01f51
7
- data.tar.gz: e6210b3ba0b09c7bfecfbddba72f779305a51645792adb01f6da8a1ebf2f9f8940b04c36933a588018c2bf5ab8a74ee04b393c4b6f6fbf8d6c08845c5cf7f8bf
6
+ metadata.gz: ec8ae92ce900948c73831b5b965e603032ee645e134b410af15f1e1b5392b5b3630252acac34ced89e3ff71d1334a37b7bd3fed212dabcc47d2ab37ee44d1294
7
+ data.tar.gz: bb8f9c77c3d0417b1e35861d7f81c8e8c82eb10963bdb32ffeef0b14f87cdfa2c8430259ddd8b7d494922434f6d38b1f8cb9f587f10373155218adec14cf36ae
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # delayed\_job\_recurring
2
+ [![Build Status](https://travis-ci.org/amitree/delayed_job_recurring.svg)](https://travis-ci.org/amitree/delayed_job_recurring)
2
3
 
3
4
  Extends delayed\_job to support recurring jobs.
4
5
 
@@ -27,12 +28,41 @@ class MyTask
27
28
  end
28
29
  ```
29
30
 
30
- And schedule it. In a rails app, you might put this in an initializer:
31
+ Finally, schedule it:
31
32
 
32
33
  ```ruby
33
34
  MyTask.schedule! # run every day at 11am Pacific time (accounting for daylight savings)
34
35
  ```
35
36
 
37
+ The best practice is to add your `MyTask.schedule!` lines to a rake file, e.g.
38
+
39
+ ```ruby
40
+ # lib/tasks/recurring_jobs.rake
41
+
42
+ namespace :recurring do
43
+ task init: :environment do
44
+ MyTask.schedule!
45
+ MyOtherTask.schedule!
46
+
47
+ if Rails.env.production?
48
+ MyProductionOnlyTask.schedule!
49
+ end
50
+ end
51
+ end
52
+ ```
53
+
54
+ and invoke this job by running `rake recurring:init` on each deployment.
55
+
56
+ Alternatively, if your app only has one instance running, you can put your
57
+ `schedule!` calls into an initializer, and then your jobs will be automatically
58
+ scheduled when your app starts. However, if you have more than one instance of
59
+ your app running in production, this will lead to a race condition and you will
60
+ end up with duplicate recurring jobs in the queue.
61
+
62
+ ## ActiveJob
63
+
64
+ Note: your task class should **not** inherit from ActiveJob::Base.
65
+
36
66
  ## Advanced usage
37
67
 
38
68
  ### Passing options to schedule
@@ -44,7 +74,7 @@ MyTask.schedule(run_at: '12:00')
44
74
  ### Running at multiples times each day
45
75
 
46
76
  ```ruby
47
- MyTask.schedule(run_every: 1.day, run_at: ['11:00', '6:00pm']
77
+ MyTask.schedule(run_every: 1.day, run_at: ['11:00', '6:00pm'])
48
78
  ```
49
79
 
50
80
  ### Running on specific days of the week
@@ -53,6 +83,22 @@ MyTask.schedule(run_every: 1.day, run_at: ['11:00', '6:00pm']
53
83
  MyTask.schedule(run_every: 1.week, run_at: ['sunday 8:00am', 'wednesday 8:00am'])
54
84
  ```
55
85
 
86
+ ### Scheduling multiple jobs of same class
87
+
88
+ By default, before scheduling a new job, the old jobs scheduled with the same class will be unscheduled.
89
+
90
+ To schedule multiple jobs with same class, pass an unique matching param `job_matching_param` and value for that matching param in each job as below:
91
+
92
+ ```ruby
93
+ MyTask.schedule(run_at: '12:00', job_matching_param: 'schedule_id', schedule_id: 2)
94
+ ```
95
+
96
+ This allows you to schedule multiple jobs with same class if value of the unique matching param(which is `schedule_id` in above example) is different in each job.
97
+
56
98
  ## Thanks!
57
99
 
58
100
  Many thanks to @ginjo and @kares for their work! This code was derived from https://gist.github.com/ginjo/3688965.
101
+
102
+ ## Contributing
103
+
104
+ [![Open Source Helpers](https://www.codetriage.com/amitree/delayed_job_recurring/badges/users.svg)](https://www.codetriage.com/amitree/delayed_job_recurring)
@@ -23,13 +23,17 @@ module Delayed
23
23
 
24
24
  # Schedule this "repeating" job
25
25
  def schedule! options = {}
26
- options = options.dup
26
+ options = options.dup.reverse_merge(@schedule_options || {})
27
+
28
+ if options[:new_instance] && !options.delete(:reentry)
29
+ return self.class.new.schedule! options.merge(reentry: true)
30
+ end
27
31
 
28
32
  if run_every = options.delete(:run_every)
29
33
  options[:run_interval] = serialize_duration(run_every)
30
34
  end
31
35
 
32
- @schedule_options = options.reverse_merge(@schedule_options || {}).reverse_merge(
36
+ @schedule_options = options.reverse_merge(
33
37
  run_at: self.class.run_at,
34
38
  timezone: self.class.timezone,
35
39
  run_interval: serialize_duration(self.class.run_every),
@@ -40,10 +44,13 @@ module Delayed
40
44
  enqueue_opts = { priority: @schedule_options[:priority], run_at: next_run_time }
41
45
  enqueue_opts[:queue] = @schedule_options[:queue] if @schedule_options[:queue]
42
46
 
43
- if Gem.loaded_specs['delayed_job'].version.to_s.first.to_i < 3
44
- Delayed::Job.enqueue self, enqueue_opts[:priority], enqueue_opts[:run_at]
45
- else
46
- Delayed::Job.enqueue self, enqueue_opts
47
+ Delayed::Job.transaction do
48
+ self.class.jobs(@schedule_options).destroy_all
49
+ if Gem.loaded_specs['delayed_job'].version.to_s.first.to_i < 3
50
+ Delayed::Job.enqueue self, enqueue_opts[:priority], enqueue_opts[:run_at]
51
+ else
52
+ Delayed::Job.enqueue self, enqueue_opts
53
+ end
47
54
  end
48
55
  end
49
56
 
@@ -157,77 +164,59 @@ module Delayed
157
164
  end
158
165
 
159
166
  # Show all jobs for this schedule
160
- def jobs
161
- ::Delayed::Job.where("(handler LIKE ?) OR (handler LIKE ?)", "--- !ruby/object:#{name} %", "--- !ruby/object:#{name}\n%")
167
+ def jobs(options = {})
168
+ options = options.with_indifferent_access
169
+
170
+ # Construct dynamic query with 'job_matching_param' if present
171
+ query = ["((handler LIKE ?) OR (handler LIKE ?))", "--- !ruby/object:#{name} %", "--- !ruby/object:#{name}\n%"]
172
+ if options[:job_matching_param].present?
173
+ matching_key = options[:job_matching_param]
174
+ matching_value = options[matching_key]
175
+ matching_yaml = yaml_quote(matching_value)
176
+ query[0] = "#{query[0]} AND handler LIKE ?"
177
+ query << "%#{matching_key}: #{matching_yaml}%"
178
+ end
179
+
180
+ ::Delayed::Job.where(query)
162
181
  end
163
182
 
164
183
  # Remove all jobs for this schedule (Stop the schedule)
165
- def unschedule
166
- jobs.each{|j| j.destroy}
184
+ def unschedule(options = {})
185
+ jobs(options).each{|j| j.destroy}
167
186
  end
168
187
 
169
188
  # Main interface to start this schedule (adds it to the jobs table).
170
189
  # Pass in a time to run the first job (nil runs the first job at run_interval from now).
171
190
  def schedule(options = {})
172
- schedule!(options) unless scheduled?
191
+ schedule!(options) unless scheduled?(options)
173
192
  end
174
193
 
175
194
  def schedule!(options = {})
176
195
  return unless Delayed::Worker.delay_jobs
177
- unschedule
178
- new.schedule!(options)
196
+ unschedule(options)
197
+ new.schedule!(options.merge(new_instance: true))
179
198
  end
180
199
 
181
- def scheduled?
182
- jobs.count > 0
200
+ def scheduled?(options = {})
201
+ jobs(options).count > 0
183
202
  end
184
203
 
185
204
  def inherited(subclass)
186
- %i(@run_at @run_interval @tz @priority).each do |var|
205
+ [:@run_at, :@run_interval, :@tz, :@priority].each do |var|
187
206
  next unless instance_variable_defined? var
188
207
  subclass.instance_variable_set var, self.instance_variable_get(var)
189
208
  subclass.instance_variable_set "#{var}_inherited", true
190
209
  end
191
210
  end
192
211
 
212
+ private
213
+ def yaml_quote(value)
214
+ # In order to ensure matching indentation, place the element inside a
215
+ # two-level hash (the first level mimicking 'schedule_options', the second
216
+ # for #{job_matching_param}), and strip out the leading "---\n:a:\n :a: "
217
+ # but keep the trailing newline.
218
+ ({a: {a: value}}).to_yaml[14..-1]
219
+ end
193
220
  end # ClassMethods
194
221
  end # RecurringJob
195
-
196
- module Task
197
- # Creates a new class wrapper around a block of code to be scheduled.
198
- def self.new(name, options, &block)
199
- task_class = Class.new
200
- task_class.class_eval do
201
- include Delayed::RecurringJob
202
-
203
- def display_name
204
- self.class.name
205
- end
206
-
207
- def perform
208
- block.call
209
- end
210
- end
211
-
212
- Object.const_set(name, task_class) if name
213
- task_class.schedule(options)
214
- return task_class
215
- end
216
-
217
- # Schedule a block of code on-the-fly.
218
- # This is a friendly wrapper for using Task.new without an explicit constant assignment.
219
- # Delayed::Task.schedule('MyNewTask', run_every: 10.minutes, run_at: 1.minute.from_now){do_some_stuff_here}
220
- # or
221
- # Delayed::Task.schedule(run_every: 10.minutes, run_at: 1.minute.from_now){do_some_stuff_here}
222
- def self.schedule(name_or_options={}, options={}, &block)
223
- case name_or_options
224
- when Hash
225
- name, options = nil, name_or_options
226
- else
227
- name = name_or_options
228
- end
229
-
230
- self.new name, options, &block
231
- end
232
- end # Task
233
222
  end # Delayed
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delayed_job_recurring
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Novak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-22 00:00:00.000000000 Z
11
+ date: 2020-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,34 +24,48 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - '='
32
46
  - !ruby/object:Gem::Version
33
- version: 3.0.0
47
+ version: 3.6.0
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - '='
39
53
  - !ruby/object:Gem::Version
40
- version: 3.0.0
54
+ version: 3.6.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec-rails
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - '='
46
60
  - !ruby/object:Gem::Version
47
- version: 3.0.1
61
+ version: 3.6.1
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - '='
53
67
  - !ruby/object:Gem::Version
54
- version: 3.0.1
68
+ version: 3.6.1
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: sqlite3
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -100,28 +114,28 @@ dependencies:
100
114
  requirements:
101
115
  - - ">="
102
116
  - !ruby/object:Gem::Version
103
- version: '4.0'
117
+ version: '3.0'
104
118
  type: :runtime
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - ">="
109
123
  - !ruby/object:Gem::Version
110
- version: '4.0'
124
+ version: '3.0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: delayed_job_active_record
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
116
130
  - !ruby/object:Gem::Version
117
- version: '4.0'
131
+ version: '0'
118
132
  type: :runtime
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
- version: '4.0'
138
+ version: '0'
125
139
  description: Extends delayed_job to support recurring jobs, including timezone support
126
140
  email: engineering@amitree.com
127
141
  executables: []
@@ -142,17 +156,16 @@ require_paths:
142
156
  - lib
143
157
  required_ruby_version: !ruby/object:Gem::Requirement
144
158
  requirements:
145
- - - "~>"
159
+ - - ">"
146
160
  - !ruby/object:Gem::Version
147
- version: '2.0'
161
+ version: '1.9'
148
162
  required_rubygems_version: !ruby/object:Gem::Requirement
149
163
  requirements:
150
164
  - - ">="
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0'
153
167
  requirements: []
154
- rubyforge_project:
155
- rubygems_version: 2.2.2
168
+ rubygems_version: 3.0.6
156
169
  signing_key:
157
170
  specification_version: 4
158
171
  summary: Recurring jobs for delayed_job