sidekiq-cron 1.9.0 → 1.12.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b26393b7aa972d9a769d851269600f51c61feff8c3d2b5cbe611eed0e21b704d
4
- data.tar.gz: 1822ffdf4ebe54db931394f38acf3eca8552953396d8fc1848aa3ec89d1164d1
3
+ metadata.gz: aaa6af217265c4e60b29018b984b43a4316b2618e52ce874db670e41ecadf85b
4
+ data.tar.gz: f70a50a90508ceb32bad90b8b2b6a880fb460f308dfa81f7380152742bb939cf
5
5
  SHA512:
6
- metadata.gz: 8fe8be5571ecb428191894a7d433fd6b2f8098607ad4de23f7cfe030b71895eed66cc8a218bf53684b235a5422b4895a676963f7bc02ab1deb06fae4982a34db
7
- data.tar.gz: b75e0b6928d263590ba7a97beca37205bd50123d0118ee49312a106573bf1a7b640f75c8ef1f76198a3da94fe19a6c9c9fa4bd3d357898590f251732d9a34d43
6
+ metadata.gz: ef95b33d15c1867a3dc6cc096080af6f2fab50c4460d8be24948bcd887c6c278dc3ca1a8c92db8d1ce386d24e0ceb95f53f6add336c3315fec04f808b7451475
7
+ data.tar.gz: e30e02e3bcc13f8604426d5d9e5f30e24c46a85bfd7679544975a3bdfcc0510631d363ef041f948c8a51e289a02a222fd27bba572cf57ac1697aabb917673a01
data/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 1.12.0
6
+
7
+ - Remove Sidekiq.server? check from schedule loader (https://github.com/sidekiq-cron/sidekiq-cron/pull/436)
8
+ - Parse arguments on `args=` method (https://github.com/sidekiq-cron/sidekiq-cron/pull/442)
9
+ - Only check out a Redis connection if necessary (https://github.com/sidekiq-cron/sidekiq-cron/pull/438)
10
+
11
+ ## 1.11.0
12
+
13
+ - Differentiates b/w "schedule" vs "dynamic" jobs (https://github.com/sidekiq-cron/sidekiq-cron/pull/431)
14
+ - Clears scheduled jobs upon schedule load (https://github.com/sidekiq-cron/sidekiq-cron/pull/431)
15
+ - Reduce gem size by excluding test files (https://github.com/sidekiq-cron/sidekiq-cron/pull/414)
16
+
17
+ ## 1.10.1
18
+
19
+ - Use `hset` instead of deprecated `hmset` (https://github.com/sidekiq-cron/sidekiq-cron/pull/410)
20
+
21
+ ## 1.10.0
22
+
23
+ - Remove EOL Ruby 2.6 support (https://github.com/sidekiq-cron/sidekiq-cron/pull/399)
24
+ - Add a logo for the project! (https://github.com/sidekiq-cron/sidekiq-cron/pull/402)
25
+ - Added support for ActiveRecord serialize/deserialize using GlobalID (https://github.com/sidekiq-cron/sidekiq-cron/pull/395)
26
+ - Allow for keyword args (`embedded: true`) in Poller (https://github.com/sidekiq-cron/sidekiq-cron/pull/398)
27
+ - Make last_enqueue_time be always an instance of Time (https://github.com/sidekiq-cron/sidekiq-cron/pull/354)
28
+ - Fix argument error problem update from 1.6.0 to newer (https://github.com/sidekiq-cron/sidekiq-cron/pull/392)
29
+ - Clear old jobs while loading the jobs from schedule via the schedule loader (https://github.com/sidekiq-cron/sidekiq-cron/pull/405)
30
+
31
+ ## 1.9.1
32
+
33
+ - Always enqueue via Active Job interface when defined in cron job config (https://github.com/sidekiq-cron/sidekiq-cron/pull/381)
34
+ - Fix schedule.yml YAML load errors on Ruby 3.1 (https://github.com/sidekiq-cron/sidekiq-cron/pull/386)
35
+ - Require Fugit v1.8 to refactor internals (https://github.com/sidekiq-cron/sidekiq-cron/pull/385)
36
+
5
37
  ## 1.9.0
6
38
 
7
39
  - Sidekiq v7 support (https://github.com/sidekiq-cron/sidekiq-cron/pull/369)
@@ -39,7 +71,7 @@ All notable changes to this project will be documented in this file.
39
71
  ## 1.4.0
40
72
 
41
73
  - Fix buttons order in job show view (https://github.com/sidekiq-cron/sidekiq-cron/pull/302)
42
- - Dark Mode support in UI (https://github.com/sidekiq-cron/sidekiq-cron/pull/317/282)
74
+ - Dark Mode support in UI (https://github.com/sidekiq-cron/sidekiq-cron/pull/282)
43
75
  - Remove invocation of deprecated Redis functionality (https://github.com/sidekiq-cron/sidekiq-cron/pull/318)
44
76
  - Internal code cleanup (https://github.com/sidekiq-cron/sidekiq-cron/pull/317)
45
77
  - Optimize gem size (https://github.com/sidekiq-cron/sidekiq-cron/pull/322)
data/Gemfile CHANGED
@@ -1,3 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ # To test different Sidekiq versions
6
+ gem "sidekiq", ENV.fetch("SIDEKIQ_VERSION", ">= 6")
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # Sidekiq-Cron
1
+ ![Sidekiq-Cron](logos/cover.png)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/sidekiq-cron.svg)](https://badge.fury.io/rb/sidekiq-cron)
4
4
  [![Build Status](https://github.com/sidekiq-cron/sidekiq-cron/workflows/CI/badge.svg?branch=master)](https://github.com/sidekiq-cron/sidekiq-cron/actions)
5
- [![Coverage Status](https://coveralls.io/repos/github/ondrejbartas/sidekiq-cron/badge.svg?branch=master)](https://coveralls.io/github/ondrejbartas/sidekiq-cron?branch=master)
5
+ [![codecov](https://codecov.io/gh/sidekiq-cron/sidekiq-cron/branch/master/graph/badge.svg?token=VK9IVLIaY8)](https://codecov.io/gh/sidekiq-cron/sidekiq-cron)
6
6
 
7
7
  > A scheduling add-on for [Sidekiq](https://sidekiq.org/)
8
8
 
@@ -26,12 +26,6 @@ Before upgrading to a new version, please read our [Changelog](CHANGELOG.md).
26
26
 
27
27
  ## Installation
28
28
 
29
- ### Requirements
30
-
31
- - Redis 2.8 or greater is required (Redis 3.0.3 or greater is recommended for large scale use)
32
- - Sidekiq 4.2 or greater is required (for Sidekiq < 4 use version sidekiq-cron 0.3.1)
33
- - Sidekiq 6.5 requires Sidekiq-Cron 1.5+
34
-
35
29
  Install the gem:
36
30
 
37
31
  ```
@@ -48,7 +42,7 @@ gem "sidekiq-cron"
48
42
 
49
43
  ## Getting Started
50
44
 
51
- ### Job properties
45
+ ### Job properties
52
46
 
53
47
  ```ruby
54
48
  {
@@ -57,12 +51,13 @@ gem "sidekiq-cron"
57
51
  'cron' => '1 * * * *', # execute at 1 minute of every hour, ex: 12:01, 13:01, 14:01, ...
58
52
  'class' => 'MyClass',
59
53
  # OPTIONAL
54
+ 'source' => 'dynamic', # source of the job, `schedule`/`dynamic` (default: `dynamic`)
60
55
  'queue' => 'name of queue',
61
56
  'args' => '[Array or Hash] of arguments which will be passed to perform method',
62
57
  'date_as_argument' => true, # add the time of execution as last argument of the perform method
63
58
  'active_job' => true, # enqueue job through Rails 4.2+ Active Job interface
64
59
  'queue_name_prefix' => 'prefix', # Rails 4.2+ Active Job queue with prefix
65
- 'queue_name_delimiter' => '.', # Rails 4.2+ Active Job queue with custom delimiter
60
+ 'queue_name_delimiter' => '.', # Rails 4.2+ Active Job queue with custom delimiter (default: '_')
66
61
  'description' => 'A sentence describing what work this job performs'
67
62
  'status' => 'disabled' # default: enabled
68
63
  }
@@ -141,6 +136,8 @@ which will ensure that arguments you are passing to it will be symbolized when p
141
136
 
142
137
  #### Adding Cron job
143
138
 
139
+ Refer to [Schedule vs Dynamic jobs](#schedule-vs-dynamic-jobs) to understand the difference.
140
+
144
141
  ```ruby
145
142
  class HardWorker
146
143
  include Sidekiq::Worker
@@ -171,6 +168,26 @@ unless job.save
171
168
  end
172
169
  ```
173
170
 
171
+ Use ActiveRecord models as arguments
172
+
173
+ ```rb
174
+ class Person < ApplicationRecord
175
+ end
176
+
177
+ class HardWorker < ActiveJob::Base
178
+ queue_as :default
179
+
180
+ def perform(person)
181
+ puts "person: #{person}"
182
+ end
183
+ end
184
+
185
+
186
+ person = Person.create(id: 1)
187
+ Sidekiq::Cron::Job.create(name: 'Hard worker - every 5min', cron: '*/5 * * * *', class: 'HardWorker', args: person)
188
+ # => true
189
+ ```
190
+
174
191
  Load more jobs from hash:
175
192
 
176
193
  ```ruby
@@ -209,7 +226,7 @@ array = [
209
226
  Sidekiq::Cron::Job.load_from_array array
210
227
  ```
211
228
 
212
- Bang-suffixed methods will remove jobs that are not present in the given hash/array, update jobs that have the same names, and create new ones when the names are previously unknown.
229
+ Bang-suffixed methods will remove jobs where source is `schedule` and are not present in the given hash/array, update jobs that have the same names, and create new ones when the names are previously unknown.
213
230
 
214
231
  ```ruby
215
232
  Sidekiq::Cron::Job.load_from_hash! hash
@@ -248,7 +265,9 @@ Sidekiq.configure_server do |config|
248
265
  schedule_file = "config/users_schedule.yml"
249
266
 
250
267
  if File.exist?(schedule_file)
251
- Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
268
+ schedule = YAML.load_file(schedule_file)
269
+
270
+ Sidekiq::Cron::Job.load_from_hash!(schedule, source: "schedule")
252
271
  end
253
272
  end
254
273
  end
@@ -301,6 +320,16 @@ job.status
301
320
  job.enque!
302
321
  ```
303
322
 
323
+ ### Schedule vs Dynamic jobs
324
+
325
+ There are two potential job sources: `schedule` and `dynamic`.
326
+ Jobs associated with schedule files are labeled as `schedule` as their source,
327
+ whereas jobs created at runtime without the `source=schedule` argument are classified as `dynamic`.
328
+
329
+ The key distinction lies in how these jobs are managed.
330
+ When a schedule is loaded, any stale `schedule` jobs are automatically removed to ensure synchronization within the schedule.
331
+ The `dynamic` jobs remain unaffected by this process.
332
+
304
333
  ### How to start scheduling?
305
334
 
306
335
  Just start Sidekiq workers by running:
@@ -316,7 +345,7 @@ add `require 'sidekiq/cron/web'` after `require 'sidekiq/web'`.
316
345
 
317
346
  With this, you will get:
318
347
 
319
- ![Web UI](examples/web-cron-ui.jpeg)
348
+ ![Web UI](docs/images/web-cron-ui.jpeg)
320
349
 
321
350
  ## Under the hood
322
351
 
@@ -1,4 +1,5 @@
1
1
  require 'fugit'
2
+ require 'globalid'
2
3
  require 'sidekiq'
3
4
  require 'sidekiq/cron/support'
4
5
  require 'sidekiq/options'
@@ -15,13 +16,17 @@ module Sidekiq
15
16
  # Use the exists? method if we're on a newer version of Redis.
16
17
  REDIS_EXISTS_METHOD = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new("7.0.0") || Gem.loaded_specs['redis'].version < Gem::Version.new('4.2') ? :exists : :exists?
17
18
 
19
+ # Use serialize/deserialize key of GlobalID.
20
+ GLOBALID_KEY = "_sc_globalid"
21
+
18
22
  # Crucial part of whole enqueuing job.
19
23
  def should_enque? time
24
+ return false unless status == "enabled"
25
+ return false unless not_past_scheduled_time?(time)
26
+ return false unless not_enqueued_after?(time)
27
+
20
28
  enqueue = Sidekiq.redis do |conn|
21
- status == "enabled" &&
22
- not_past_scheduled_time?(time) &&
23
- not_enqueued_after?(time) &&
24
- conn.zadd(job_enqueued_key, formatted_enqueue_time(time), formatted_last_time(time))
29
+ conn.zadd(job_enqueued_key, formatted_enqueue_time(time), formatted_last_time(time))
25
30
  end
26
31
  enqueue == true || enqueue == 1
27
32
  end
@@ -45,7 +50,7 @@ module Sidekiq
45
50
 
46
51
  # Enqueue cron job to queue.
47
52
  def enque! time = Time.now.utc
48
- @last_enqueue_time = time.strftime(LAST_ENQUEUE_TIME_FORMAT)
53
+ @last_enqueue_time = time
49
54
 
50
55
  klass_const =
51
56
  begin
@@ -56,7 +61,7 @@ module Sidekiq
56
61
 
57
62
  jid =
58
63
  if klass_const
59
- if defined?(ActiveJob::Base) && klass_const < ActiveJob::Base
64
+ if is_active_job?(klass_const)
60
65
  enqueue_active_job(klass_const).try :provider_job_id
61
66
  else
62
67
  enqueue_sidekiq_worker(klass_const)
@@ -74,8 +79,8 @@ module Sidekiq
74
79
  Sidekiq.logger.debug { "enqueued #{@name}: #{@message}" }
75
80
  end
76
81
 
77
- def is_active_job?
78
- @active_job || defined?(ActiveJob::Base) && Sidekiq::Cron::Support.constantize(@klass.to_s) < ActiveJob::Base
82
+ def is_active_job?(klass = nil)
83
+ @active_job || defined?(ActiveJob::Base) && (klass || Sidekiq::Cron::Support.constantize(@klass.to_s)) < ActiveJob::Base
79
84
  rescue NameError
80
85
  false
81
86
  end
@@ -85,7 +90,8 @@ module Sidekiq
85
90
  end
86
91
 
87
92
  def enqueue_args
88
- date_as_argument? ? @args + [Time.now.to_f] : @args
93
+ args = date_as_argument? ? @args + [Time.now.to_f] : @args
94
+ deserialize_argument(args)
89
95
  end
90
96
 
91
97
  def enqueue_active_job(klass_const)
@@ -157,19 +163,19 @@ module Sidekiq
157
163
  # }
158
164
  # }
159
165
  #
160
- def self.load_from_hash hash
166
+ def self.load_from_hash(hash, options = {})
161
167
  array = hash.map do |key, job|
162
168
  job['name'] = key
163
169
  job
164
170
  end
165
- load_from_array array
171
+ load_from_array(array, options)
166
172
  end
167
173
 
168
174
  # Like #load_from_hash.
169
175
  # If exists old jobs in Redis but removed from args, destroy old jobs.
170
- def self.load_from_hash! hash
176
+ def self.load_from_hash!(hash, options = {})
171
177
  destroy_removed_jobs(hash.keys)
172
- load_from_hash(hash)
178
+ load_from_hash(hash, options)
173
179
  end
174
180
 
175
181
  # Load cron jobs from Array.
@@ -189,10 +195,10 @@ module Sidekiq
189
195
  # }
190
196
  # ]
191
197
  #
192
- def self.load_from_array array
198
+ def self.load_from_array(array, options = {})
193
199
  errors = {}
194
200
  array.each do |job_data|
195
- job = new(job_data)
201
+ job = new(job_data.merge(options))
196
202
  errors[job.name] = job.errors unless job.save
197
203
  end
198
204
  errors
@@ -200,10 +206,10 @@ module Sidekiq
200
206
 
201
207
  # Like #load_from_array.
202
208
  # If exists old jobs in Redis but removed from args, destroy old jobs.
203
- def self.load_from_array! array
209
+ def self.load_from_array!(array, options = {})
204
210
  job_names = array.map { |job| job["name"] }
205
211
  destroy_removed_jobs(job_names)
206
- load_from_array(array)
212
+ load_from_array(array, options)
207
213
  end
208
214
 
209
215
  # Get all cron jobs.
@@ -234,12 +240,11 @@ module Sidekiq
234
240
  def self.find name
235
241
  # If name is hash try to get name from it.
236
242
  name = name[:name] || name['name'] if name.is_a?(Hash)
243
+ return unless exists? name
237
244
 
238
245
  output = nil
239
246
  Sidekiq.redis do |conn|
240
- if exists? name
241
- output = Job.new conn.hgetall( redis_key(name) )
242
- end
247
+ output = Job.new conn.hgetall( redis_key(name) )
243
248
  end
244
249
  output if output && output.valid?
245
250
  end
@@ -262,7 +267,7 @@ module Sidekiq
262
267
  end
263
268
 
264
269
  attr_accessor :name, :cron, :description, :klass, :args, :message
265
- attr_reader :last_enqueue_time, :fetch_missing_args
270
+ attr_reader :last_enqueue_time, :fetch_missing_args, :source
266
271
 
267
272
  def initialize input_args = {}
268
273
  args = Hash[input_args.map{ |k, v| [k.to_s, v] }]
@@ -272,6 +277,7 @@ module Sidekiq
272
277
  @name = args["name"]
273
278
  @cron = args["cron"]
274
279
  @description = args["description"] if args["description"]
280
+ @source = args["source"] == "schedule" ? "schedule" : "dynamic"
275
281
 
276
282
  # Get class from klass or class.
277
283
  @klass = args["klass"] || args["class"]
@@ -288,7 +294,7 @@ module Sidekiq
288
294
 
289
295
  # Get right arguments for job.
290
296
  @symbolize_args = args["symbolize_args"] == true || ("#{args["symbolize_args"]}" =~ (/^(true|t|yes|y|1)$/i)) == 0 || false
291
- @args = args["args"].nil? ? [] : parse_args( args["args"] )
297
+ @args = parse_args(args["args"])
292
298
 
293
299
  @date_as_argument = args["date_as_argument"] == true || ("#{args["date_as_argument"]}" =~ (/^(true|t|yes|y|1)$/i)) == 0 || false
294
300
 
@@ -398,21 +404,27 @@ module Sidekiq
398
404
 
399
405
  # Export job data to hash.
400
406
  def to_hash
401
- {
407
+ hash = {
402
408
  name: @name,
403
409
  klass: @klass.to_s,
404
410
  cron: @cron,
405
411
  description: @description,
412
+ source: @source,
406
413
  args: @args.is_a?(String) ? @args : Sidekiq.dump_json(@args || []),
407
- date_as_argument: date_as_argument? ? "1" : "0",
408
414
  message: @message.is_a?(String) ? @message : Sidekiq.dump_json(@message || {}),
409
415
  status: @status,
410
416
  active_job: @active_job ? "1" : "0",
411
417
  queue_name_prefix: @active_job_queue_name_prefix,
412
418
  queue_name_delimiter: @active_job_queue_name_delimiter,
413
- last_enqueue_time: @last_enqueue_time.to_s,
419
+ last_enqueue_time: serialized_last_enqueue_time,
414
420
  symbolize_args: symbolize_args? ? "1" : "0",
415
421
  }
422
+
423
+ if date_as_argument?
424
+ hash.merge!(date_as_argument: "1")
425
+ end
426
+
427
+ hash
416
428
  end
417
429
 
418
430
  def errors
@@ -428,15 +440,7 @@ module Sidekiq
428
440
  errors << "'cron' must be set"
429
441
  else
430
442
  begin
431
- c = Fugit.do_parse(@cron)
432
-
433
- # Since `Fugit.do_parse` might yield a Fugit::Duration or an EtOrbi::EoTime
434
- # https://github.com/floraison/fugit#fugitparses
435
- if c.is_a?(Fugit::Cron)
436
- @parsed_cron = c
437
- else
438
- errors << "'cron' -> #{@cron.inspect} -> not a cron but a #{c.class}"
439
- end
443
+ @parsed_cron = Fugit.do_parse_cronish(@cron)
440
444
  rescue => e
441
445
  errors << "'cron' -> #{@cron.inspect} -> #{e.class}: #{e.message}"
442
446
  end
@@ -467,7 +471,7 @@ module Sidekiq
467
471
  conn.sadd self.class.jobs_key, [redis_key]
468
472
 
469
473
  # Add informations for this job!
470
- conn.hmset redis_key, *hash_to_redis(to_hash)
474
+ conn.hset redis_key, to_hash.transform_values! { |v| v || "" }
471
475
 
472
476
  # Add information about last time! - don't enque right after scheduler poller starts!
473
477
  time = Time.now.utc
@@ -480,7 +484,7 @@ module Sidekiq
480
484
  def save_last_enqueue_time
481
485
  Sidekiq.redis do |conn|
482
486
  # Update last enqueue time.
483
- conn.hset redis_key, 'last_enqueue_time', @last_enqueue_time
487
+ conn.hset redis_key, 'last_enqueue_time', serialized_last_enqueue_time
484
488
  end
485
489
  end
486
490
 
@@ -527,7 +531,7 @@ module Sidekiq
527
531
 
528
532
  # Remove "removed jobs" between current jobs and new jobs
529
533
  def self.destroy_removed_jobs new_job_names
530
- current_job_names = Sidekiq::Cron::Job.all.map(&:name)
534
+ current_job_names = Sidekiq::Cron::Job.all.filter_map { |j| j.name if j.source == "schedule" }
531
535
  removed_job_names = current_job_names - new_job_names
532
536
  removed_job_names.each { |j| Sidekiq::Cron::Job.destroy(j) }
533
537
  removed_job_names
@@ -562,22 +566,14 @@ module Sidekiq
562
566
  "#{status == "enabled" ? 0 : 1}_#{name}".downcase
563
567
  end
564
568
 
569
+ def args=(args)
570
+ @args = parse_args(args)
571
+ end
572
+
565
573
  private
566
574
 
567
575
  def parsed_cron
568
- @parsed_cron ||= begin
569
- c = Fugit.parse(@cron)
570
-
571
- # Since `Fugit.parse` might yield a Fugit::Duration or an EtOrbi::EoTime
572
- # https://github.com/floraison/fugit#fugitparses
573
- if c.is_a?(Fugit::Cron)
574
- c
575
- else
576
- errors << "'cron' -> #{@cron.inspect} -> not a cron but a #{c.class}"
577
- end
578
- rescue => e
579
- errors << "'cron' -> #{@cron.inspect} -> #{e.class}: #{e.message}"
580
- end
576
+ @parsed_cron ||= Fugit.parse_cronish(@cron)
581
577
  end
582
578
 
583
579
  def not_enqueued_after?(time)
@@ -589,6 +585,8 @@ module Sidekiq
589
585
  # try to load JSON, then failover to string array.
590
586
  def parse_args(args)
591
587
  case args
588
+ when GlobalID::Identification
589
+ [convert_to_global_id_hash(args)]
592
590
  when String
593
591
  begin
594
592
  parsed_args = Sidekiq.load_json(args)
@@ -597,8 +595,10 @@ module Sidekiq
597
595
  [*args]
598
596
  end
599
597
  when Hash
598
+ args = serialize_argument(args)
600
599
  symbolize_args? ? [symbolize_args(args)] : [args]
601
600
  when Array
601
+ args = serialize_argument(args)
602
602
  symbolize_args? ? symbolize_args(args) : args
603
603
  else
604
604
  [*args]
@@ -669,9 +669,55 @@ module Sidekiq
669
669
  self.class.jid_history_key @name
670
670
  end
671
671
 
672
- # Give Hash returns array for using it for redis.hmset
673
- def hash_to_redis hash
674
- hash.flat_map{ |key, value| [key, value || ""] }
672
+ def serialized_last_enqueue_time
673
+ @last_enqueue_time&.strftime(LAST_ENQUEUE_TIME_FORMAT)
674
+ end
675
+
676
+ def convert_to_global_id_hash(argument)
677
+ { GLOBALID_KEY => argument.to_global_id.to_s }
678
+ rescue URI::GID::MissingModelIdError
679
+ raise "Unable to serialize #{argument.class} " \
680
+ "without an id. (Maybe you forgot to call save?)"
681
+ end
682
+
683
+ def deserialize_argument(argument)
684
+ case argument
685
+ when String
686
+ argument
687
+ when Array
688
+ argument.map { |arg| deserialize_argument(arg) }
689
+ when Hash
690
+ if serialized_global_id?(argument)
691
+ deserialize_global_id argument
692
+ else
693
+ argument.transform_values { |v| deserialize_argument(v) }
694
+ end
695
+ else
696
+ argument
697
+ end
698
+ end
699
+
700
+ def serialized_global_id?(hash)
701
+ hash.size == 1 && hash.include?(GLOBALID_KEY)
702
+ end
703
+
704
+ def deserialize_global_id(hash)
705
+ GlobalID::Locator.locate hash[GLOBALID_KEY]
706
+ end
707
+
708
+ def serialize_argument(argument)
709
+ case argument
710
+ when GlobalID::Identification
711
+ convert_to_global_id_hash(argument)
712
+ when Array
713
+ argument.map { |arg| serialize_argument(arg) }
714
+ when Hash
715
+ argument.each_with_object({}) do |(key, value), hash|
716
+ hash[key] = serialize_argument(value)
717
+ end
718
+ else
719
+ argument
720
+ end
675
721
  end
676
722
  end
677
723
  end
@@ -14,7 +14,7 @@ module Sidekiq
14
14
  attr_reader :cron_poller
15
15
 
16
16
  # Add cron poller and execute normal initialize of Sidekiq launcher.
17
- def initialize(config)
17
+ def initialize(config, **kwargs)
18
18
  config[:cron_poll_interval] = DEFAULT_POLL_INTERVAL if config[:cron_poll_interval].nil?
19
19
 
20
20
  @cron_poller = Sidekiq::Cron::Poller.new(config) if config[:cron_poll_interval] > 0
@@ -2,20 +2,18 @@ require 'sidekiq'
2
2
  require 'sidekiq/cron/job'
3
3
  require 'sidekiq/options'
4
4
 
5
- if Sidekiq.server?
6
- Sidekiq.configure_server do |config|
7
- schedule_file = Sidekiq::Options[:cron_schedule_file] || 'config/schedule.yml'
5
+ Sidekiq.configure_server do |config|
6
+ schedule_file = Sidekiq::Options[:cron_schedule_file] || 'config/schedule.yml'
8
7
 
9
- if File.exist?(schedule_file)
10
- config.on(:startup) do
11
- schedule = YAML.load(ERB.new(IO.read(schedule_file)).result)
12
- if schedule.kind_of?(Hash)
13
- Sidekiq::Cron::Job.load_from_hash schedule
14
- elsif schedule.kind_of?(Array)
15
- Sidekiq::Cron::Job.load_from_array schedule
16
- else
17
- raise "Not supported schedule format. Confirm your #{schedule_file}"
18
- end
8
+ if File.exist?(schedule_file)
9
+ config.on(:startup) do
10
+ schedule = Sidekiq::Cron::Support.load_yaml(ERB.new(IO.read(schedule_file)).result)
11
+ if schedule.kind_of?(Hash)
12
+ Sidekiq::Cron::Job.load_from_hash!(schedule, source: "schedule")
13
+ elsif schedule.kind_of?(Array)
14
+ Sidekiq::Cron::Job.load_from_array!(schedule, source: "schedule")
15
+ else
16
+ raise "Not supported schedule format. Confirm your #{schedule_file}"
19
17
  end
20
18
  end
21
19
  end
@@ -32,6 +32,14 @@ module Sidekiq
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ def self.load_yaml(src)
37
+ if Psych::VERSION > "4.0"
38
+ YAML.safe_load(src, permitted_classes: [Symbol], aliases: true)
39
+ else
40
+ YAML.load(src)
41
+ end
42
+ end
35
43
  end
36
44
  end
37
45
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sidekiq
4
4
  module Cron
5
- VERSION = "1.9.0"
5
+ VERSION = "1.12.0"
6
6
  end
7
7
  end
@@ -3,11 +3,15 @@ require 'sidekiq'
3
3
  module Sidekiq
4
4
  module Options
5
5
  def self.[](key)
6
- options_field ? Sidekiq.public_send(options_field)[key] : Sidekiq[key]
6
+ self.config[key]
7
7
  end
8
8
 
9
9
  def self.[]=(key, value)
10
- options_field ? Sidekiq.public_send(options_field)[key] = value : Sidekiq[key] = value
10
+ self.config[key] = value
11
+ end
12
+
13
+ def self.config
14
+ options_field ? Sidekiq.public_send(options_field) : Sidekiq
11
15
  end
12
16
 
13
17
  def self.options_field
data/sidekiq-cron.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  "LICENSE.txt",
16
16
  "README.md"
17
17
  ]
18
- s.files = Dir.glob('lib/**/*') + Dir.glob('test/**/*') + [
18
+ s.files = Dir.glob('lib/**/*') + [
19
19
  "CHANGELOG.md",
20
20
  "Gemfile",
21
21
  "LICENSE.txt",
@@ -24,15 +24,17 @@ Gem::Specification.new do |s|
24
24
  "sidekiq-cron.gemspec",
25
25
  ]
26
26
 
27
- s.required_ruby_version = ">= 2.6"
27
+ s.required_ruby_version = ">= 2.7"
28
28
 
29
- s.add_dependency("fugit", "~> 1")
30
- s.add_dependency("sidekiq", ">= 4.2.1")
29
+ s.add_dependency("fugit", "~> 1.8")
30
+ s.add_dependency("sidekiq", ">= 6")
31
+ s.add_dependency("globalid", ">= 1.0.1")
31
32
 
32
33
  s.add_development_dependency("minitest", "~> 5.15")
33
- s.add_development_dependency("mocha", "~> 1.14")
34
+ s.add_development_dependency("mocha", "~> 2.1")
34
35
  s.add_development_dependency("rack", "~> 2.2")
35
36
  s.add_development_dependency("rack-test", "~> 1.1")
36
37
  s.add_development_dependency("rake", "~> 13.0")
37
38
  s.add_development_dependency("simplecov", "~> 0.21")
39
+ s.add_development_dependency("simplecov-cobertura", "~> 2.1")
38
40
  end