sidekiq-scheduler 5.0.3 → 5.0.4

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: d26f3947b1ef031bc393203e79975cfcc5159d32f7ff3d07a1b3858621d167d4
4
- data.tar.gz: f921936d4d0a8f9942e98cc67da8404738af852042e2f8b23e9c818be14c8b26
3
+ metadata.gz: 17e9ebdeaa24ce323d7b3f94c7481d741e0f0f6d3daeded5eaef94f8b1e09f37
4
+ data.tar.gz: c8e1d62c30406b7928444bdd05a0668aac6bbb47c1bc6a752ff795dbf67b8bb2
5
5
  SHA512:
6
- metadata.gz: 1fdea51e227d0eafcce6cc6973e9e9349788ffd3ff947c3967ca4eceae7fe4c47ec485a72194c36e11b623a3cfa372ba583d6305df57896d7c39fc6c3f687618
7
- data.tar.gz: c217f9992d5cb3fcb78d11dae5273cccdae276fd2d6a7c1166b4faf6aae92ad3b8c2253af2f4f94fffca4027fe0c9ca6720386cb7406d592baa514b63ee5f6ef
6
+ metadata.gz: f94c5008ef8a2ec39837adc8a25145b27c15abf2514ba22f9c2341b1306431aecfcceb877f8b07fe05c0daa09e26e6b4df3f6e10c118893fe78b11ca6b6751cb
7
+ data.tar.gz: 61e7f37615f1c575d51c0e55593c4a82362829e21533182e60ec7a125fe76273e44bc055f6449a43185c083370eb1e416a0f1031671e537b6b85cec0ff3a218b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ # 5.0.4
2
+ - [**FIX**] Ensure rufus-scheduler has a default rufus_scheduler_options value [#434](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/426)
3
+ - [**ENHANCEMENT**] Remove code related to sidekiq < 6 [#443](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/443)
4
+ - [**ENHANCEMENT**] Change cache-control to `private` [#446](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/446)
5
+ - [**ENHANCEMENT**] Increase compatibility range with tilt dependency [#458](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/458)
6
+ - [**ENHANCEMENT**] Ensure we support Ruby 3.3 [#461](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/461)
7
+ - [**ENHANCEMENT**] Use Redis MULTI command (https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/464)
8
+ - [**ENHANCEMENT**] Don't attempt to set jon next_time when job is nil [#466](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/466)
9
+ - [**ENHANCEMENT**] Improvements to prevent jobs been enqueued multiple times due to a delay in job execution [#463](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/463)
10
+ - [**FIX**] Prevent stack level too deep error by implementing `to_hash` method [#470](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/470)
11
+ - [**ENHANCEMENT**] Support new Sidekiq model for registering UI plugins [#472](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/472)
12
+ - [**ENHANCEMENT**] Stop testing against Ruby 2.7 and 3.0 [#472](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/472#discussion_r1663197863)
13
+ - [**ENHANCEMENT**] Display `at` and `in` in the dashboard [#291](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/291)
14
+ - [**ENHANCEMENT**] Docs enhancements [#442](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/442), [#449](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/449), [#457](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/457), [#465](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/465), [58e1835](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/58e18351054fc3c264b2b5a684173316f674c386)
15
+
16
+
1
17
  # 5.0.3
2
18
 
3
19
  - [**FIX**] Fix "uppercase character in header name: Cache-Control" [#432](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/432)
data/README.md CHANGED
@@ -45,6 +45,8 @@ class HelloWorld
45
45
  end
46
46
  ```
47
47
 
48
+ __Note:__ In Sidekiq v6.3 `Sidekiq::Job` was introduced as an alias for `Sidekiq::Worker`. `Sidekiq::Worker` has been officially deprecated in Sidekiq v7 although it still exists for backwards compatibility. It is therefore recommended to use `include Sidekiq::Job` in the above example unless an older version of Sidekiq is required.
49
+
48
50
  ``` yaml
49
51
  # config/sidekiq.yml
50
52
 
@@ -55,6 +57,9 @@ end
55
57
  class: HelloWorld
56
58
  ```
57
59
 
60
+ > [!NOTE]
61
+ > sidekiq-scheduler uses [fugit](https://github.com/floraison/fugit) under the hood, which supports up to six arguments as the cron string, [see](https://github.com/floraison/fugit?tab=readme-ov-file#the-second-extension).
62
+
58
63
  Run sidekiq:
59
64
 
60
65
  ``` sh
@@ -122,7 +127,7 @@ The schedule is configured through the `:scheduler:` -> `:schedule` config entry
122
127
 
123
128
  # Deconstructs a hash defined as the `args` to keyword arguments.
124
129
  #
125
- # `flase` by default.
130
+ # `false` by default.
126
131
  #
127
132
  # Example
128
133
  #
@@ -208,7 +213,7 @@ At, and in types push jobs only once. `at` schedules in a point in time:
208
213
  at: '3001/01/01'
209
214
  ```
210
215
 
211
- You can specify any string that `DateTime.parse` and `Chronic` understand. To enable Chronic
216
+ You can specify any string that `DateTime.parse` and `Chronic` understand. To enable [Chronic](https://github.com/mojombo/chronic)
212
217
  strings, you must add it as a dependency.
213
218
 
214
219
  `in` triggers after a time duration has elapsed:
@@ -359,7 +364,7 @@ MyRegularJob:
359
364
  Then we can conditionally load it via an initializer:
360
365
 
361
366
  ```ruby
362
- # config/initializer/sidekiq.rb
367
+ # config/initializers/sidekiq.rb
363
368
  if ENV.fetch("IS_SCHEDULER", false)
364
369
  Sidekiq.configure_server do |config|
365
370
  config.on(:startup) do
@@ -59,6 +59,17 @@ module SidekiqScheduler
59
59
  SidekiqScheduler::SidekiqAdapter.sidekiq_queues(sidekiq_config)
60
60
  end
61
61
 
62
+ def to_hash
63
+ {
64
+ enabled: enabled?,
65
+ dynamic: dynamic?,
66
+ dynamic_every: dynamic_every?,
67
+ shedule: schedule,
68
+ listened_queues_only: listened_queues_only?,
69
+ rufus_scheduler_options: rufus_scheduler_options
70
+ }
71
+ end
72
+
62
73
  private
63
74
 
64
75
  attr_reader :scheduler_config
@@ -1,14 +1,27 @@
1
1
  require 'sidekiq/web' unless defined?(Sidekiq::Web)
2
2
 
3
- ASSETS_PATH = File.expand_path('../../../web/assets', __dir__)
3
+ if SidekiqScheduler::SidekiqAdapter::SIDEKIQ_GTE_7_3_0
4
4
 
5
- Sidekiq::Web.register(SidekiqScheduler::Web)
6
- Sidekiq::Web.tabs['recurring_jobs'] = 'recurring-jobs'
7
- Sidekiq::Web.locales << File.expand_path("#{File.dirname(__FILE__)}/../../../web/locales")
5
+ # Locale and asset cache is configured in `.regiester`
6
+ Sidekiq::Web.register(SidekiqScheduler::Web,
7
+ name: "recurring_jobs",
8
+ tab: ["Recurring Jobs"],
9
+ index: ["recurring-jobs"],
10
+ root_dir: File.expand_path("../../../web", File.dirname(__FILE__)),
11
+ asset_paths: ["stylesheets-scheduler"]) do |app|
12
+ # add middleware or additional settings here
13
+ end
14
+
15
+ else
16
+
17
+ ASSETS_PATH = File.expand_path('../../../web/assets', __dir__)
18
+
19
+ Sidekiq::Web.register(SidekiqScheduler::Web)
20
+ Sidekiq::Web.tabs['recurring_jobs'] = 'recurring-jobs'
21
+ Sidekiq::Web.locales << File.expand_path("#{File.dirname(__FILE__)}/../../../web/locales")
8
22
 
9
- if Sidekiq::VERSION >= '6.0.0'
10
23
  Sidekiq::Web.use Rack::Static, urls: ['/stylesheets-scheduler'],
11
24
  root: ASSETS_PATH,
12
25
  cascade: true,
13
- header_rules: [[:all, { 'cache-control' => 'public, max-age=86400' }]]
26
+ header_rules: [[:all, { 'cache-control' => 'private, max-age=86400' }]]
14
27
  end
@@ -38,7 +38,7 @@ module SidekiqScheduler
38
38
  #
39
39
  # @return [String] with the job's interval
40
40
  def interval
41
- @attributes['cron'] || @attributes['interval'] || @attributes['every']
41
+ @attributes['cron'] || @attributes['interval'] || @attributes['every'] || @attributes['at'] || @attributes['in']
42
42
  end
43
43
 
44
44
  # Returns the queue of the job
@@ -24,6 +24,15 @@ module SidekiqScheduler
24
24
  @scheduler_instance.load_schedule!
25
25
  end
26
26
 
27
+ # This method is needed to avoid exposing unnecessary information.
28
+ # Because ActiveSupport's `as_json` traverses instance values to convert the object to a hash
29
+ # unless it responds to `to_hash`.
30
+ def to_hash
31
+ {
32
+ scheduler: @scheduler_instance.to_hash
33
+ }
34
+ end
35
+
27
36
  private
28
37
 
29
38
  def set_current_scheduler_options(config)
@@ -130,9 +130,9 @@ module SidekiqScheduler
130
130
  def self.register_job_instance(job_name, time)
131
131
  job_key = pushed_job_key(job_name)
132
132
  registered, _ = Sidekiq.redis do |r|
133
- r.pipelined do |pipeline|
134
- pipeline.zadd(job_key, time.to_i, time.to_i)
135
- pipeline.expire(job_key, REGISTERED_JOBS_THRESHOLD_IN_SECONDS)
133
+ r.multi do |m|
134
+ m.zadd(job_key, time.to_i, time.to_i)
135
+ m.expire(job_key, REGISTERED_JOBS_THRESHOLD_IN_SECONDS)
136
136
  end
137
137
  end
138
138
 
@@ -58,7 +58,7 @@ module SidekiqScheduler
58
58
  self.dynamic = config.dynamic?
59
59
  self.dynamic_every = config.dynamic_every?
60
60
  self.listened_queues_only = config.listened_queues_only?
61
- self.rufus_scheduler_options = config.rufus_scheduler_options
61
+ self.rufus_scheduler_options = config.rufus_scheduler_options || {}
62
62
  end
63
63
 
64
64
  # the Rufus::Scheduler jobs that are scheduled
@@ -128,6 +128,8 @@ module SidekiqScheduler
128
128
  schedule, options = SidekiqScheduler::RufusUtils.normalize_schedule_options(config_interval_type)
129
129
 
130
130
  rufus_job = new_job(name, interval_type, config, schedule, options)
131
+ return unless rufus_job
132
+
131
133
  @scheduled_jobs[name] = rufus_job
132
134
  SidekiqScheduler::Utils.update_job_next_time(name, rufus_job.next_time)
133
135
 
@@ -248,6 +250,12 @@ module SidekiqScheduler
248
250
  end
249
251
  end
250
252
 
253
+ def to_hash
254
+ {
255
+ scheduler_config: @scheduler_config.to_hash
256
+ }
257
+ end
258
+
251
259
  private
252
260
 
253
261
  attr_reader :scheduler_config
@@ -256,7 +264,15 @@ module SidekiqScheduler
256
264
  options = options.merge({ :job => true, :tags => [name] })
257
265
 
258
266
  rufus_scheduler.send(interval_type, schedule, options) do |job, time|
259
- idempotent_job_enqueue(name, time, SidekiqScheduler::Utils.sanitize_job_config(config)) if job_enabled?(name)
267
+ if job_enabled?(name)
268
+ conf = SidekiqScheduler::Utils.sanitize_job_config(config)
269
+
270
+ if job.is_a?(Rufus::Scheduler::CronJob)
271
+ idempotent_job_enqueue(name, SidekiqScheduler::Utils.calc_cron_run_time(job.cron_line, time.utc), conf)
272
+ else
273
+ idempotent_job_enqueue(name, time, conf)
274
+ end
275
+ end
260
276
  end
261
277
  end
262
278
 
@@ -4,6 +4,7 @@ module SidekiqScheduler
4
4
  class SidekiqAdapter
5
5
  SIDEKIQ_GTE_6_5_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('6.5.0')
6
6
  SIDEKIQ_GTE_7_0_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('7.0.0')
7
+ SIDEKIQ_GTE_7_3_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('7.3.0')
7
8
 
8
9
  def self.fetch_scheduler_config_from_sidekiq(sidekiq_config)
9
10
  return {} if sidekiq_config.nil?
@@ -141,5 +141,39 @@ module SidekiqScheduler
141
141
  def self.update_job_last_time(name, last_time)
142
142
  SidekiqScheduler::RedisManager.set_job_last_time(name, last_time) if last_time
143
143
  end
144
+
145
+ # Try to figure out when the cron job was supposed to run.
146
+ #
147
+ # Rufus calls the scheduler block with the current time and not the time the block was scheduled to run.
148
+ # This means under certain conditions you could have a job get scheduled multiple times because `time.to_i` is used
149
+ # to key the job in redis. If one server is under load and Rufus tries to run the jobs 1 seconds after the other
150
+ # server then the job will be queued twice.
151
+ # This method essentially makes a best guess at when this job was supposed to run and return that.
152
+ #
153
+ # @param [Fugit::Cron] cron
154
+ # @param [Time] time
155
+ #
156
+ # @return [Time]
157
+ def self.calc_cron_run_time(cron, time)
158
+ time = time.round # remove sub seconds to prevent rounding errors.
159
+ next_t = cron.next_time(time).utc
160
+ previous_t = cron.previous_time(time).utc
161
+ # The `time` var is some point between `previous_t` and `next_t`.
162
+ # Figure out how far off we are from each side in seconds.
163
+ next_diff = next_t - time
164
+ previous_diff = time - previous_t
165
+
166
+ if next_diff == previous_diff
167
+ # In the event `time` is exactly between `previous_t` and `next_t` the diff will not be equal to
168
+ # `cron.rough_frequency`. In that case we round down.
169
+ cron.rough_frequency == next_diff ? time : previous_t
170
+ elsif next_diff > previous_diff
171
+ # We are closer to the previous run time so return that.
172
+ previous_t
173
+ else
174
+ # We are closer to the next run time so return that.
175
+ next_t
176
+ end
177
+ end
144
178
  end
145
179
  end
@@ -1,3 +1,3 @@
1
1
  module SidekiqScheduler
2
- VERSION = "5.0.3"
2
+ VERSION = "5.0.4"
3
3
  end
data/web/locales/cs.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  cs:
2
+ "Recurring Jobs": Pravidelně opakované
2
3
  recurring_jobs: Pravidelně opakované
3
4
  name: Jméno
4
5
  description: Popis
data/web/locales/de.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  de:
2
+ "Recurring Jobs": Wiederkehrende Jobs
2
3
  recurring_jobs: Wiederkehrende Jobs
3
4
  name: Name
4
5
  description: Beschreibung
data/web/locales/en.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  en:
2
+ "Recurring Jobs": Recurring Jobs
2
3
  recurring_jobs: Recurring Jobs
3
4
  name: Name
4
5
  description: Description
data/web/locales/es.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  es:
2
+ "Recurring Jobs": Tareas Recurrentes
2
3
  recurring_jobs: Tareas Recurrentes
3
4
  name: Nombre
4
5
  description: Descripción
data/web/locales/fr.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  fr:
2
+ "Recurring Jobs": Tâches récurrentes
2
3
  recurring_jobs: Tâches récurrentes
3
4
  name: Nom
4
5
  description: Description
data/web/locales/gd.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  gd:
2
+ "Recurring Jobs": Obraichean ath-chùrsach
2
3
  recurring_jobs: Obraichean ath-chùrsach
3
4
  name: Ainm
4
5
  description: Tuairisgeul
data/web/locales/it.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  it:
2
+ "Recurring Jobs": Job ricorrenti
2
3
  recurring_jobs: Job ricorrenti
3
4
  name: Nome
4
5
  description: Descrizione
data/web/locales/ja.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  ja:
2
+ "Recurring Jobs": 定期ジョブ
2
3
  recurring_jobs: 定期ジョブ
3
4
  name: 名前
4
5
  description: 説明
data/web/locales/nl.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  nl:
2
+ "Recurring Jobs": Herhalende taken
2
3
  recurring_jobs: Herhalende taken
3
4
  name: Naam
4
5
  description: Beschrijving
data/web/locales/pl.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  pl:
2
+ "Recurring Jobs": Okresowe
2
3
  recurring_jobs: Okresowe
3
4
  name: Nazwa
4
5
  description: Opis
@@ -1,4 +1,5 @@
1
1
  pt-BR:
2
+ "Recurring Jobs": Jobs Recorrentes
2
3
  recurring_jobs: Jobs Recorrentes
3
4
  name: Nome
4
5
  description: Descrição
@@ -6,7 +7,7 @@ pt-BR:
6
7
  class: Classe
7
8
  queue: Fila
8
9
  arguments: Argumentos
9
- enqueue_now: Enfileirar agora
10
+ enqueue_now: Enfileirar agora
10
11
  last_time: Última execução
11
12
  next_time: Próxima execução
12
13
  no_next_time: Não há mais execuçoẽs
data/web/locales/ru.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  ru:
2
+ "Recurring Jobs": Расписание задач
2
3
  recurring_jobs: Расписание задач
3
4
  name: Название
4
5
  description: Описание
data/web/locales/sv.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  sv:
2
+ "Recurring Jobs": Återkommande jobb
2
3
  recurring_jobs: Återkommande jobb
3
4
  name: Namn
4
5
  description: Beskrivning
@@ -1,4 +1,5 @@
1
1
  zh-cn:
2
+ "Recurring Jobs": 周期作业
2
3
  recurring_jobs: 周期作业
3
4
  name: 名称
4
5
  description: 描述
@@ -1,42 +1,7 @@
1
- <% if Sidekiq::VERSION >= '6.0.0' %>
2
- <link href="<%= root_path %>stylesheets-scheduler/recurring_jobs.css" media="screen" rel="stylesheet" type="text/css" />
1
+ <% if SidekiqScheduler::SidekiqAdapter::SIDEKIQ_GTE_7_3_0 %>
2
+ <%= style_tag "stylesheets-scheduler/recurring_jobs.css" %>
3
3
  <% else %>
4
- <style>
5
- .recurring-jobs { border-top-left-radius: 4px; border-top-right-radius: 4px; }
6
- .recurring-jobs .title { margin-bottom: 5px; }
7
- .recurring-jobs .title .name { font-weight: bold;}
8
- .recurring-jobs .info,
9
- .recurring-jobs .description { margin-bottom: 5px; }
10
- .recurring-jobs .actions { margin-bottom: 5px; }
11
- .recurring-jobs .status,
12
- .recurring-jobs .description { font-size: 12px; }
13
- .recurring-jobs .enqueue { margin-bottom: 0.5rem }
14
-
15
- .list-group-item {
16
- background-color: #f3f3f3;
17
- color: #585454;
18
- border: 1px solid rgba(0, 0, 0, 0.1);
19
- }
20
-
21
- .list-group-item-disabled {
22
- background-color: #f3d3d3;
23
- }
24
-
25
- .toggle-all-buttons {
26
- margin-top: 20px;
27
- margin-bottom: 10px;
28
- line-height: 45px;
29
- text-align: right;
30
- }
31
-
32
- @media (max-width: 768px) {
33
- .toggle-all-buttons {
34
- margin-top: 0;
35
- text-align: left;
36
- line-height: inherit;
37
- }
38
- }
39
- </style>
4
+ <link href="<%= root_path %>stylesheets-scheduler/recurring_jobs.css" media="screen" rel="stylesheet" type="text/css" />
40
5
  <% end %>
41
6
 
42
7
  <div class="row">
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.3
4
+ version: 5.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Morton Jonuschat
8
8
  - Moove-it
9
9
  - Marcelo Lauxen
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-05-31 00:00:00.000000000 Z
13
+ date: 2024-07-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sidekiq
@@ -53,6 +53,9 @@ dependencies:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: 1.4.0
56
+ - - "<"
57
+ - !ruby/object:Gem::Version
58
+ version: '3'
56
59
  type: :runtime
57
60
  prerelease: false
58
61
  version_requirements: !ruby/object:Gem::Requirement
@@ -60,6 +63,9 @@ dependencies:
60
63
  - - ">="
61
64
  - !ruby/object:Gem::Version
62
65
  version: 1.4.0
66
+ - - "<"
67
+ - !ruby/object:Gem::Version
68
+ version: '3'
63
69
  - !ruby/object:Gem::Dependency
64
70
  name: rake
65
71
  requirement: !ruby/object:Gem::Requirement
@@ -234,7 +240,7 @@ homepage: https://sidekiq-scheduler.github.io/sidekiq-scheduler/
234
240
  licenses:
235
241
  - MIT
236
242
  metadata: {}
237
- post_install_message:
243
+ post_install_message:
238
244
  rdoc_options: []
239
245
  require_paths:
240
246
  - lib
@@ -249,8 +255,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
255
  - !ruby/object:Gem::Version
250
256
  version: '0'
251
257
  requirements: []
252
- rubygems_version: 3.2.33
253
- signing_key:
258
+ rubygems_version: 3.5.3
259
+ signing_key:
254
260
  specification_version: 4
255
261
  summary: Light weight job scheduling extension for Sidekiq
256
262
  test_files: []