dynamodb-sidekiq-scheduler 0.4 → 0.6

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: 44238e2d235ddfb9e7d9afd49f11ed04818fed695fe89f8c6a5582fdaf6fd7b8
4
- data.tar.gz: 15a508861db4aa29f69dfe8caf6dce4dd49d57f47999bb148cf0a1d2f88c1857
3
+ metadata.gz: 20ac92a2fa35e6f1e15f3307bbdd862aef92ecaafb1d16760ca9061dbbce334a
4
+ data.tar.gz: 94599cadc83d8afb968649150964f51e4dc846f74a2de81a9570906cb4facc03
5
5
  SHA512:
6
- metadata.gz: 3e9a24d3c229f41eedd44ac00922c6ce8eaa75be5757f290c70b6d51fb205dee4552b328e4836a5b85d7c89b6d8eb033a8fa382e725e400259a592e20a2e951d
7
- data.tar.gz: c8750a1a82c076d84a54cfabcdf02b463b061e2d7eddc45c87d6f5d28200d55b2eaa0d1040c6de2f9d716c25e8a45cc1ae29da6eb91f178f71d202f55da6b200
6
+ metadata.gz: 540ff094b04ca414461214101b441f40d86ded4d1a3304c3ac5a678596adf3fd52455a63a013d81f099a578f13207f2be4bf2233c7a676af72ae69a8f40ed7c5
7
+ data.tar.gz: 5a327f337bbc1ce073a8b8a9cdc4a8b5910cb02e67d39701b61f5e855b7fff729f24a2805028c19bbe14490ffcd995799f25645b1fa0a14e4096bc9216c21a9f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,56 @@
1
+ # 6.0.2
2
+ - [**FIX**] Use parser-safe web locale keys for the recurring jobs tab so the Sidekiq Web UI works with Sidekiq 8.1.3+ [#514](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/514)
3
+ - [**FIX**] Stop symbolizing scheduled job `args` hash keys so string keys from YAML/JSON are preserved when enqueuing [ca3d405](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/ca3d405e62433e3d889ebba1e3dedd3b0de0c8ef)
4
+
5
+ # 6.0.1
6
+ - [**FIX**] Fix issue with Sidekiq v7.3.0-v7.3.6 [#503](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/503)
7
+
8
+ # 6.0.0
9
+ - Check the changelog for beta1 and beta2 of this version.
10
+
11
+ # 6.0.0.beta2
12
+ - [**FIX**/**BREAKING CHANGE**] Don't clear "schedule" key on boot in `dynamic` schedule mode [#467](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/467)
13
+ - If you use sidekiq-scheduler with the `dynamic` mode, be aware that the schedule key won't be cleared on boot anymore (so maybe patches handling that in your codebase might have to be removed)
14
+ - [**FIX**] SidekiqScheduler::Manager enormous inspect output [17f9c7f](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/17f9c7ffc7f7db79a1cb047bed985f2bdf12ac92) / [#462](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/462).
15
+ - [**FIX/ENHANCEMENT**] Remove checks that would raise an error if any of the following options was not under the `scheduler` key (`enabled`, `dynamic`, `dynamic_every`, `schedule`, `listened_queues_only`, `rufus_scheduler_options`). [1e64958](https://github.com/sidekiq-scheduler/sidekiq-scheduler/commit/1e6495838aaee91cbf53fbd57c3749f0ed35dc28) / [#469](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/469)
16
+ - This was needed for those migrating from v4 to v5, but isn't anymore.
17
+
18
+ # 6.0.0.beta1
19
+ - [**ENHANCEMENT**] Adds compatibility with Sidekiq 8 [#497](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/497)
20
+ - [**BREAKING CHANGE**] Drop support for Sidekiq 7.2 and earlier [#497](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/498)
21
+
22
+ # 5.0.6
23
+ - [**FIX**] Fix typo in `config#to_hash` method [#479](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/479)
24
+ - [**FIX**] Correctly clear scheduled jobs with Scheduler#clear_schedule! [#485](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/485)
25
+ - [**FIX**] Fix scheduling of aperiodic cron jobs [#487](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/487) (see [#484](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/484) for more details as well)
26
+
27
+ # 5.0.5
28
+ - [**FIX**] Use correct folder structure for assets [#476](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/476)
29
+
30
+ # 5.0.4
31
+ - [**FIX**] Ensure rufus-scheduler has a default rufus_scheduler_options value [#434](https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues/426)
32
+ - [**ENHANCEMENT**] Remove code related to sidekiq < 6 [#443](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/443)
33
+ - [**ENHANCEMENT**] Change cache-control to `private` [#446](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/446)
34
+ - [**ENHANCEMENT**] Increase compatibility range with tilt dependency [#458](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/458)
35
+ - [**ENHANCEMENT**] Ensure we support Ruby 3.3 [#461](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/461)
36
+ - [**ENHANCEMENT**] Use Redis MULTI command (https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/464)
37
+ - [**ENHANCEMENT**] Don't attempt to set jon next_time when job is nil [#466](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/466)
38
+ - [**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)
39
+ - [**FIX**] Prevent stack level too deep error by implementing `to_hash` method [#470](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/470)
40
+ - [**ENHANCEMENT**] Support new Sidekiq model for registering UI plugins [#472](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/472)
41
+ - [**ENHANCEMENT**] Stop testing against Ruby 2.7 and 3.0 [#472](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/472#discussion_r1663197863)
42
+ - [**ENHANCEMENT**] Display `at` and `in` in the dashboard [#291](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/291)
43
+ - [**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)
44
+
45
+
46
+ # 5.0.3
47
+
48
+ - [**FIX**] Fix "uppercase character in header name: Cache-Control" [#432](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/432)
49
+ - [**ENHANCEMENT**] Add gd translation [#433](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/433)
50
+ - [**ENHANCEMENT**] Add French translation [#435](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/435)
51
+ - [**FIX**] Remove usage of deprecated Redis command `zrangebyscore` [#437](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/437)
52
+ - [**ENHANCEMENT**] Add the ability to force a job args hash to be deconstructed to keyword arguments [#440](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/440)
53
+
1
54
  # 5.0.2
2
55
 
3
56
  - [**FIX**] Fix YARD docblocks. [#427](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/427)
@@ -8,10 +61,10 @@
8
61
  - [**ENHANCEMENT**] Adds Ruby 3.2 to the CI matrix. [#420](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/420)
9
62
  - [**DOCS**] README: refer to v5 as released. [#421](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/421)
10
63
  - [**FIX**] Fix dependency on Rails `.present?` method. [#425](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/425)
11
-
64
+
12
65
  # 5.0.0
13
66
 
14
- - [**FIX**] Ensure generated scheduled time has a precision of 3 miliseconds. [#418](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/418)
67
+ - [**FIX**] Ensure generated scheduled time has a precision of 3 milliseconds. [#418](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/418)
15
68
 
16
69
  *Note 1:* Check [# 5.0.0.beta1](#500beta1) & [# 5.0.0.beta2](#500beta2) releases for breaking changes.
17
70
 
@@ -27,7 +80,7 @@
27
80
  - [**BREAKING CHANGE**] Moves all sidekiq-scheduler config options under the `scheduler` key in the `sidekiq.yml` file [#412](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/412)
28
81
  - If you're migrating from v4 to v5, any `sidekiq-scheduler` config you may have in your `sidekiq.yml` should be moved under the `scheduler` key.
29
82
  - See [#412](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/412) to see which are the config options that you need to move under the `scheduler` key.
30
-
83
+
31
84
  - [**BREAKING CHANGE**] Drop support for EOL Ruby & Sidekiq versions (Ruby: `2.5.x` & `2.6.x`; Sidekiq: `4.x` & `5.x`) [#411](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/411)
32
85
 
33
86
  - [**FIX**] Add support for Sidekiq 7 [#410](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/410)
@@ -64,6 +117,6 @@
64
117
  - [**ENHANCEMENT**] Highlight disabled jobs [#369](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/369)
65
118
  - [**BREAKING CHANGE**] Require redis 4.2.0 [#370](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/370)
66
119
  - [**FIX**] Fixes redis deprecation warning regarding `exists` [#370](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/370)
67
- - [**BREAKING CHANGE**] Remove dependecy on thwait and e2mmap [#371](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/371)
120
+ - [**BREAKING CHANGE**] Remove dependency on thwait and e2mmap [#371](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/371)
68
121
  - Support Ruby 3.1 [#373](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/373)
69
- - [**BREAKING CHANGE**] Set rufus_scheduler_options via sidekiq.yml file as configuration option [#375](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/375)
122
+ - [**BREAKING CHANGE**] Set rufus_scheduler_options via sidekiq.yml file as configuration option [#375](https://github.com/sidekiq-scheduler/sidekiq-scheduler/pull/375)
data/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
  `sidekiq-scheduler` is an extension to [Sidekiq](http://github.com/mperham/sidekiq) that
19
19
  pushes jobs in a scheduled way, mimicking cron utility.
20
20
 
21
- __Note:__ Current branch contains work of the v5 release, if you are looking for version 2.2.\*, 3.\*, or 4.\*, go to [2.2-stable branch](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/2.2-stable) / [v3-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v3-stable) / [v4-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v4-stable).
21
+ __Note:__ Current branch contains work of the v6 release, if you are looking for version 2.2.\*, 3.\*, 4.\*, or 5.\*, go to [2.2-stable branch](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/2.2-stable) / [v3-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v3-stable) / [v4-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v4-stable) / [v5-stable](https://github.com/sidekiq-scheduler/sidekiq-scheduler/tree/v5-stable).
22
22
 
23
23
  ## Installation
24
24
 
@@ -37,7 +37,7 @@ gem install sidekiq-scheduler
37
37
  require 'sidekiq-scheduler'
38
38
 
39
39
  class HelloWorld
40
- include Sidekiq::Worker
40
+ include Sidekiq::Job
41
41
 
42
42
  def perform
43
43
  puts 'Hello world'
@@ -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
@@ -119,6 +124,25 @@ The schedule is configured through the `:scheduler:` -> `:schedule` config entry
119
124
 
120
125
  # Enable / disable a job. All jobs are enabled by default.
121
126
  enabled: true
127
+
128
+ # Deconstructs a hash defined as the `args` to keyword arguments.
129
+ #
130
+ # `false` by default.
131
+ #
132
+ # Example
133
+ #
134
+ # my_job:
135
+ # cron: '0 0 * * * *'
136
+ # class: MyJob
137
+ # args: { foo: 'bar', hello: 'world' }
138
+ # keyword_argument: true
139
+ #
140
+ # class MyJob < ActiveJob::Base
141
+ # def perform(foo:, hello:)
142
+ # # ...
143
+ # end
144
+ # end
145
+ keyword_argument: true
122
146
  ```
123
147
 
124
148
  ### Schedule metadata
@@ -189,7 +213,7 @@ At, and in types push jobs only once. `at` schedules in a point in time:
189
213
  at: '3001/01/01'
190
214
  ```
191
215
 
192
- 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)
193
217
  strings, you must add it as a dependency.
194
218
 
195
219
  `in` triggers after a time duration has elapsed:
@@ -313,7 +337,7 @@ You can also override the thread pool size in Rufus Scheduler by setting the fol
313
337
  ## Notes about running on Multiple Hosts
314
338
 
315
339
  Under normal conditions, `cron` and `at` jobs are pushed once regardless of the number of `sidekiq-scheduler` running instances,
316
- assumming that time deltas between hosts is less than 24 hours.
340
+ assuming that time deltas between hosts is less than 24 hours.
317
341
 
318
342
  Non-normal conditions that could push a specific job multiple times are:
319
343
  - high cpu load + a high number of jobs scheduled at the same time, like 100 jobs
@@ -323,7 +347,7 @@ Non-normal conditions that could push a specific job multiple times are:
323
347
 
324
348
  ### Suggested setup for Multiple Hosts using Heroku and Rails
325
349
 
326
- Configuration options `every`, `interval` and `in` will push once per host. This may be undesirable. One way to achieve single jobs per the schedule would be to manually designate a host as the scheduler. The goal is to have a single scheduler process running across all your hosts.
350
+ Configuration options `every`, `interval` and `in` will push once per host. This may be undesirable. One way to achieve single jobs per the schedule would be to manually designate a host as the scheduler. The goal is to have a single scheduler process running across all your hosts.
327
351
 
328
352
  This can be achieved by using an environment variable and controlling the number of dynos. In Rails, you can read this variable during initialization and then conditionally load your config file.
329
353
 
@@ -340,7 +364,7 @@ MyRegularJob:
340
364
  Then we can conditionally load it via an initializer:
341
365
 
342
366
  ```ruby
343
- # config/initializer/sidekiq.rb
367
+ # config/initializers/sidekiq.rb
344
368
  if ENV.fetch("IS_SCHEDULER", false)
345
369
  Sidekiq.configure_server do |config|
346
370
  config.on(:startup) do
@@ -360,7 +384,7 @@ worker: bundle exec sidekiq -q default
360
384
  scheduler: IS_SCHEDULER=true bundle exec sidekiq -q default
361
385
  ```
362
386
 
363
- When running via Heroku, you set your `scheduler` process to have 1 dyno. This will ensure you have at most 1 worker loading the schedule.
387
+ When running via Heroku, you set your `scheduler` process to have 1 dyno. This will ensure you have at most 1 worker loading the schedule.
364
388
 
365
389
  ## Notes on when Sidekiq worker is down
366
390
 
@@ -373,7 +397,7 @@ Possible solutions include:
373
397
  - Zero downtime deploy for sidekiq workers: keep at least one worker up during whole deploy and only restart/shut it down after when new one has started
374
398
  - Running scheduler inside your unicorn/rails processes (if you already have zero downtime deploy set up for these)
375
399
 
376
- Each option has it's own pros and cons.
400
+ Each option has it's own pros and cons.
377
401
 
378
402
  ## Notes when running multiple Sidekiq processors on the same Redis
379
403
 
@@ -456,6 +480,8 @@ run Sidekiq::Web
456
480
 
457
481
  ![Sidekiq Web Integration](https://github.com/sidekiq-scheduler/sidekiq-scheduler/raw/master/images/recurring-jobs-ui-tab.png)
458
482
 
483
+ ![Sidekiq Web Integration Dark Mode](https://github.com/sidekiq-scheduler/sidekiq-scheduler/raw/master/images/recurring-jobs-ui-tab-dark.png)
484
+
459
485
  ## ActiveJob integration
460
486
 
461
487
  When using sidekiq-scheduler with ActiveJob your jobs can just extend `ApplicationJob` as usual, without the `require` and `include` boilerplate. Under the hood Rails will load up the scheduler and include the worker module for you.
@@ -470,7 +496,7 @@ end
470
496
 
471
497
  ## The Spring preloader and Testing your initializer via Rails console
472
498
 
473
- If you're pulling in your schedule from a YML file via an initializer as shown, be aware that the Spring application preloader included with Rails will interefere with testing via the Rails console.
499
+ If you're pulling in your schedule from a YML file via an initializer as shown, be aware that the Spring application preloader included with Rails will interfere with testing via the Rails console.
474
500
 
475
501
  **Spring will not reload initializers** unless the initializer is changed. Therefore, if you're making a change to your YML schedule file and reloading Rails console to see the change, Spring will make it seem like your modified schedule is not being reloaded.
476
502
 
@@ -515,7 +541,7 @@ MIT License
515
541
 
516
542
  ## Copyright
517
543
 
518
- - Copyright 2021 - 2022 Marcelo Lauxen.
544
+ - Copyright 2021 - 2024 Marcelo Lauxen.
519
545
  - Copyright 2013 - 2022 Moove-IT.
520
546
  - Copyright 2012 Morton Jonuschat.
521
547
  - Some parts copyright 2010 Ben VandenBos.
@@ -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
+ schedule: 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,22 @@
1
1
  require 'sidekiq/web' unless defined?(Sidekiq::Web)
2
2
 
3
- ASSETS_PATH = File.expand_path('../../../web/assets', __dir__)
3
+ # Locale and asset cache is configured in `cfg.register`
4
+ args = {
5
+ name: "recurring_jobs",
6
+ tab: ["recurring_jobs"],
7
+ index: ["recurring-jobs"],
8
+ root_dir: File.expand_path("../../../web", File.dirname(__FILE__)),
9
+ asset_paths: ["stylesheets-scheduler"]
10
+ }
4
11
 
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")
8
-
9
- if Sidekiq::VERSION >= '6.0.0'
10
- Sidekiq::Web.use Rack::Static, urls: ['/stylesheets-scheduler'],
11
- root: ASSETS_PATH,
12
- cascade: true,
13
- header_rules: [[:all, { 'Cache-Control' => 'public, max-age=86400' }]]
12
+ if SidekiqScheduler::SidekiqAdapter::SIDEKIQ_GTE_8_0_0
13
+ Sidekiq::Web.configure do |cfg|
14
+ cfg.register(SidekiqScheduler::Web, **args) do |app|
15
+ # add middleware or additional settings here
16
+ end
17
+ end
18
+ else
19
+ Sidekiq::Web.register(SidekiqScheduler::Web, **args) do |app|
20
+ # add middleware or additional settings here
21
+ end
14
22
  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
@@ -13,7 +13,7 @@ module SidekiqScheduler
13
13
 
14
14
  @scheduler_instance = SidekiqScheduler::Scheduler.new(config)
15
15
  SidekiqScheduler::Scheduler.instance = @scheduler_instance
16
- Sidekiq.schedule = config.schedule if @scheduler_instance.enabled
16
+ Sidekiq.schedule = config.schedule if @scheduler_instance.enabled && !@scheduler_instance.dynamic
17
17
  end
18
18
 
19
19
  def stop
@@ -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)
@@ -106,7 +106,7 @@ module SidekiqScheduler
106
106
  #
107
107
  # @return [Array] array with all the changed job names
108
108
  def self.get_schedule_changes(from, to)
109
- Sidekiq.redis { |r| r.zrangebyscore(schedules_changed_key, from, "(#{to}") }
109
+ SidekiqScheduler::SidekiqAdapter.redis_zrangebyscore(schedules_changed_key, from, "(#{to}")
110
110
  end
111
111
 
112
112
  # Register a schedule change for a given job
@@ -121,7 +121,7 @@ module SidekiqScheduler
121
121
  Sidekiq.redis { |r| r.del(schedules_changed_key) unless r.type(schedules_changed_key) == 'zset' }
122
122
  end
123
123
 
124
- # Removes a queued job instance
124
+ # Registers a queued job instance
125
125
  #
126
126
  # @param [String] job_name The name of the job
127
127
  # @param [Time] time The time at which the job was cleared by the scheduler
@@ -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
 
@@ -65,7 +65,7 @@ module SidekiqScheduler
65
65
  end
66
66
  alias_method :schedule!, :reload_schedule!
67
67
 
68
- # Retrive the schedule configuration for the given name
68
+ # Retrieve the schedule configuration for the given name
69
69
  # if the name is nil it returns a hash with all the
70
70
  # names end their schedules.
71
71
  def get_schedule(name = nil)
@@ -17,7 +17,7 @@ module SidekiqScheduler
17
17
  # saying we will have to do it somehow still)
18
18
  #
19
19
  # NOTE: ^ Keeping this TODO here for now, in a future version of this project
20
- # we will remove those attr acessors and use only our config object. For now,
20
+ # we will remove those attr accessors and use only our config object. For now,
21
21
  # let's keep as it is.
22
22
 
23
23
  # Set to enable or disable the scheduler.
@@ -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
 
@@ -194,7 +196,7 @@ module SidekiqScheduler
194
196
  @rufus_scheduler = nil
195
197
  end
196
198
 
197
- @@scheduled_jobs = {}
199
+ @scheduled_jobs = {}
198
200
 
199
201
  rufus_scheduler
200
202
  end
@@ -248,6 +250,16 @@ 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
+
259
+ def inspect
260
+ "#<SidekiqScheduler::Scheduler enabled=#{enabled} dynamic=#{dynamic} dynamic_every=#{dynamic_every} listened_queues_only=#{listened_queues_only} rufus_scheduler_options=#{rufus_scheduler_options}>"
261
+ end
262
+
251
263
  private
252
264
 
253
265
  attr_reader :scheduler_config
@@ -256,7 +268,15 @@ module SidekiqScheduler
256
268
  options = options.merge({ :job => true, :tags => [name] })
257
269
 
258
270
  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)
271
+ if job_enabled?(name)
272
+ conf = SidekiqScheduler::Utils.sanitize_job_config(config)
273
+
274
+ if job.is_a?(Rufus::Scheduler::CronJob)
275
+ idempotent_job_enqueue(name, SidekiqScheduler::Utils.calc_cron_run_time(job.cron_line, time.to_t), conf)
276
+ else
277
+ idempotent_job_enqueue(name, time.to_t, conf)
278
+ end
279
+ end
260
280
  end
261
281
  end
262
282
 
@@ -287,12 +307,12 @@ module SidekiqScheduler
287
307
  end
288
308
 
289
309
  # Adds a Hash with schedule metadata as the last argument to call the worker.
290
- # It currently returns the schedule time as a Float number representing the milisencods
310
+ # It currently returns the schedule time as a Float number representing the milliseconds
291
311
  # since epoch.
292
312
  #
293
313
  # @example with hash argument
294
314
  # arguments_with_metadata({value: 1}, scheduled_at: Time.now.round(3))
295
- # #=> [{value: 1}, {scheduled_at: <miliseconds since epoch>}]
315
+ # #=> [{value: 1}, {scheduled_at: <milliseconds since epoch>}]
296
316
  #
297
317
  # @param args [Array|Hash]
298
318
  # @param metadata [Hash]
@@ -328,11 +348,7 @@ module SidekiqScheduler
328
348
  def prepare_arguments(config)
329
349
  config['class'] = SidekiqScheduler::Utils.try_to_constantize(config['class'])
330
350
 
331
- if config['args'].is_a?(Hash)
332
- config['args'].symbolize_keys! if config['args'].respond_to?(:symbolize_keys!)
333
- else
334
- config['args'] = Array(config['args'])
335
- end
351
+ config['args'] = Array(config['args']) unless config['args'].is_a?(Hash)
336
352
 
337
353
  config
338
354
  end
@@ -1,79 +1,40 @@
1
1
  module SidekiqScheduler
2
- class OptionNotSupportedAnymore < StandardError; end
3
-
4
2
  class SidekiqAdapter
5
- SIDEKIQ_GTE_6_5_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('6.5.0')
6
- SIDEKIQ_GTE_7_0_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('7.0.0')
3
+ SIDEKIQ_GTE_7_3_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('7.3.0')
4
+ SIDEKIQ_GTE_8_0_0 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('8.0.0')
7
5
 
8
6
  def self.fetch_scheduler_config_from_sidekiq(sidekiq_config)
9
7
  return {} if sidekiq_config.nil?
10
8
 
11
- check_using_old_sidekiq_scheduler_config!(sidekiq_config)
12
-
13
- if SIDEKIQ_GTE_6_5_0
14
- sidekiq_config.fetch(:scheduler, {})
15
- else
16
- sidekiq_config.options.fetch(:scheduler, {})
17
- end
18
- end
19
-
20
- def self.check_using_old_sidekiq_scheduler_config!(sidekiq_config)
21
- %i[enabled dynamic dynamic_every schedule listened_queues_only rufus_scheduler_options].each do |option|
22
- if SIDEKIQ_GTE_7_0_0
23
- if sidekiq_config.key?(option)
24
- raise OptionNotSupportedAnymore, ":#{option} option should be under the :scheduler: key"
25
- end
26
- elsif SIDEKIQ_GTE_6_5_0
27
- unless sidekiq_config[option].nil?
28
- raise OptionNotSupportedAnymore, ":#{option} option should be under the :scheduler: key"
29
- end
30
- else
31
- if sidekiq_config.options.key?(option)
32
- raise OptionNotSupportedAnymore, ":#{option} option should be under the :scheduler: key"
33
- end
34
- end
35
- end
9
+ sidekiq_config.fetch(:scheduler, {})
36
10
  end
37
11
 
38
12
  def self.start_schedule_manager(sidekiq_config:, schedule_manager:)
39
- if SIDEKIQ_GTE_6_5_0
40
- sidekiq_config[:schedule_manager] = schedule_manager
41
- sidekiq_config[:schedule_manager].start
42
- else
43
- sidekiq_config.options[:schedule_manager] = schedule_manager
44
- sidekiq_config.options[:schedule_manager].start
45
- end
13
+ sidekiq_config[:schedule_manager] = schedule_manager
14
+ sidekiq_config[:schedule_manager].start
46
15
  end
47
16
 
48
17
  def self.stop_schedule_manager(sidekiq_config:)
49
- if SIDEKIQ_GTE_6_5_0
50
- sidekiq_config[:schedule_manager].stop
51
- else
52
- sidekiq_config.options[:schedule_manager].stop
53
- end
18
+ sidekiq_config[:schedule_manager].stop
54
19
  end
55
20
 
56
21
  def self.sidekiq_queues(sidekiq_config)
57
- if SIDEKIQ_GTE_7_0_0
58
- if sidekiq_config.nil? || (sidekiq_config.respond_to?(:empty?) && sidekiq_config.empty?)
59
- Sidekiq.instance_variable_get(:@config).queues.map(&:to_s)
60
- else
61
- sidekiq_config.queues.map(&:to_s)
62
- end
63
- elsif SIDEKIQ_GTE_6_5_0
64
- Sidekiq[:queues].map(&:to_s)
22
+ if sidekiq_config.nil? || (sidekiq_config.respond_to?(:empty?) && sidekiq_config.empty?)
23
+ Sidekiq.instance_variable_get(:@config).queues.map(&:to_s)
65
24
  else
66
- Sidekiq.options[:queues].map(&:to_s)
25
+ sidekiq_config.queues.map(&:to_s)
67
26
  end
68
27
  end
69
28
 
70
29
  def self.redis_key_exists?(key_name)
71
30
  Sidekiq.redis do |r|
72
- if SIDEKIQ_GTE_7_0_0
73
- r.exists(key_name) > 0
74
- else
75
- r.exists?(key_name)
76
- end
31
+ r.exists(key_name) > 0
32
+ end
33
+ end
34
+
35
+ def self.redis_zrangebyscore(key, from, to)
36
+ Sidekiq.redis do |r|
37
+ r.zrange(key, from, to, "BYSCORE")
77
38
  end
78
39
  end
79
40
  end
@@ -60,9 +60,11 @@ module SidekiqScheduler
60
60
  # @param [Array, Hash] args The parameters passed to the klass initializer
61
61
  #
62
62
  # @return [Object] instance of the class klass
63
- def self.initialize_active_job(klass, args)
63
+ def self.initialize_active_job(klass, args, keyword_argument = false)
64
64
  if args.is_a?(Array)
65
65
  klass.new(*args)
66
+ elsif args.is_a?(Hash) && keyword_argument
67
+ klass.new(**symbolize_keys(args))
66
68
  else
67
69
  klass.new(args)
68
70
  end
@@ -71,7 +73,7 @@ module SidekiqScheduler
71
73
  # Returns true if the enqueuing needs to be done for an ActiveJob
72
74
  # class false otherwise.
73
75
  #
74
- # @param [Class] klass the class to check is decendant from ActiveJob
76
+ # @param [Class] klass the class to check is descendant from ActiveJob
75
77
  #
76
78
  # @return [Boolean]
77
79
  def self.active_job_enqueue?(klass)
@@ -94,7 +96,7 @@ module SidekiqScheduler
94
96
  queue: config['queue']
95
97
  }.keep_if { |_, v| !v.nil? }
96
98
 
97
- initialize_active_job(config['class'], config['args']).enqueue(options)
99
+ initialize_active_job(config['class'], config['args'], config['keyword_argument']).enqueue(options)
98
100
  end
99
101
 
100
102
  # Removes the hash values associated to the rufus metadata keys.
@@ -139,5 +141,41 @@ module SidekiqScheduler
139
141
  def self.update_job_last_time(name, last_time)
140
142
  SidekiqScheduler::RedisManager.set_job_last_time(name, last_time) if last_time
141
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.floor # remove sub seconds to prevent rounding errors.
159
+ return time if cron.match?(time) # If the time is a perfect match then return it.
160
+
161
+ next_t = cron.next_time(time).to_t
162
+ previous_t = cron.previous_time(time).to_t
163
+ # The `time` var is some point between `previous_t` and `next_t`.
164
+ # Figure out how far off we are from each side in seconds.
165
+ next_diff = next_t - time
166
+ previous_diff = time - previous_t
167
+
168
+ if next_diff == previous_diff
169
+ # In the event `time` is exactly between `previous_t` and `next_t` the diff will not be equal to
170
+ # `cron.rough_frequency`. In that case we round down.
171
+ cron.rough_frequency == next_diff ? time : previous_t
172
+ elsif next_diff > previous_diff
173
+ # We are closer to the previous run time so return that.
174
+ previous_t
175
+ else
176
+ # We are closer to the next run time so return that.
177
+ next_t
178
+ end
179
+ end
142
180
  end
143
181
  end
@@ -1,3 +1,3 @@
1
1
  module SidekiqScheduler
2
- VERSION = '0.4'
2
+ VERSION = "0.6"
3
3
  end
@@ -6,9 +6,29 @@ module SidekiqScheduler
6
6
  # Hook into *Sidekiq::Web* app which adds a new '/recurring-jobs' page
7
7
 
8
8
  module Web
9
- VIEW_PATH = File.expand_path('../../../web/views', __FILE__)
9
+ VIEW_PATH = File.expand_path(SidekiqAdapter::SIDEKIQ_GTE_8_0_0 ? '../../../web/views' : '../../../web/views/sidekiq73', __FILE__)
10
+
11
+ module Helpers
12
+ def sidekiq_scheduler_fetch_route_param(key)
13
+ if SidekiqAdapter::SIDEKIQ_GTE_8_0_0
14
+ route_params(key)
15
+ else
16
+ route_params[key]
17
+ end
18
+ end
19
+
20
+ def sidekiq_scheduler_fetch_url_param(key)
21
+ if SidekiqAdapter::SIDEKIQ_GTE_8_0_0
22
+ url_params(key)
23
+ else
24
+ params[key]
25
+ end
26
+ end
27
+ end
10
28
 
11
29
  def self.registered(app)
30
+ app.helpers(Helpers)
31
+
12
32
  app.get '/recurring-jobs' do
13
33
  @presented_jobs = JobPresenter.build_collection(Sidekiq.schedule!)
14
34
 
@@ -16,7 +36,7 @@ module SidekiqScheduler
16
36
  end
17
37
 
18
38
  app.post '/recurring-jobs/:name/enqueue' do
19
- schedule = Sidekiq.get_schedule(params[:name])
39
+ schedule = Sidekiq.get_schedule(sidekiq_scheduler_fetch_route_param(:name))
20
40
  SidekiqScheduler::Scheduler.instance.enqueue_job(schedule)
21
41
  redirect "#{root_path}recurring-jobs"
22
42
  end
@@ -24,7 +44,7 @@ module SidekiqScheduler
24
44
  app.post '/recurring-jobs/:name/toggle' do
25
45
  Sidekiq.reload_schedule!
26
46
 
27
- SidekiqScheduler::Scheduler.instance.toggle_job_enabled(params[:name])
47
+ SidekiqScheduler::Scheduler.instance.toggle_job_enabled(sidekiq_scheduler_fetch_route_param(:name))
28
48
  redirect "#{root_path}recurring-jobs"
29
49
  end
30
50
 
@@ -36,7 +56,7 @@ module SidekiqScheduler
36
56
  end
37
57
 
38
58
  app.post '/recurring-jobs/toggle-all' do
39
- SidekiqScheduler::Scheduler.instance.toggle_all_jobs(params[:action] == 'enable')
59
+ SidekiqScheduler::Scheduler.instance.toggle_all_jobs(sidekiq_scheduler_fetch_url_param(:action) == 'enable')
40
60
  redirect "#{root_path}recurring-jobs"
41
61
  end
42
62
 
@@ -1,5 +1,4 @@
1
1
  require 'sidekiq'
2
- require 'tilt/erb'
3
2
 
4
3
  require_relative 'sidekiq/scheduler'
5
4
  require_relative 'sidekiq-scheduler/version'
@@ -0,0 +1,81 @@
1
+ .sidekiq-scheduler .job-name {
2
+ color: var(--color-primary);
3
+ display: block;
4
+ font-size: var(--font-size);
5
+ font-weight: 700;
6
+ }
7
+
8
+ .sidekiq-scheduler .queue {
9
+ text-align: right;
10
+ }
11
+
12
+ .sidekiq-scheduler .btn-xs {
13
+ padding: 1px 5px;
14
+ font-size: var(--font-size-small);
15
+ line-height: 1.5;
16
+ }
17
+
18
+ .sidekiq-scheduler .description,
19
+ .sidekiq-scheduler .last-time,
20
+ .sidekiq-scheduler .next-time {
21
+ font-size: var(--font-size-small);
22
+ }
23
+
24
+ .sidekiq-scheduler .description {
25
+ padding-top: 10px;
26
+ }
27
+
28
+ .sidekiq-scheduler .inline {
29
+ display: inline;
30
+ }
31
+
32
+ .sidekiq-scheduler .job-list .job {
33
+ background-color: var(--color-elevated);
34
+ border: 1px solid var(--color-border);
35
+ box-shadow: 0 2px 4px 0 var(--color-shadow);
36
+ padding: 10px;
37
+ }
38
+
39
+ .sidekiq-scheduler .column-2 {
40
+ float: left;
41
+ width: 50%;
42
+ }
43
+
44
+ .sidekiq-scheduler .column-3 {
45
+ float: left;
46
+ width: 33.33%;
47
+ }
48
+
49
+ .sidekiq-scheduler .row:after {
50
+ content: "";
51
+ display: table;
52
+ clear: both;
53
+ }
54
+
55
+ .sidekiq-scheduler .job.disabled-job {
56
+ background-color: #f3d3d3;
57
+ color: #585454;
58
+ }
59
+
60
+ @media (prefers-color-scheme: dark) {
61
+ .sidekiq-scheduler .job.disabled-job {
62
+ background-color: #4f0b0b;
63
+ }
64
+ }
65
+
66
+ .sidekiq-scheduler .disabled-job .next-time {
67
+ text-decoration: line-through;
68
+ }
69
+
70
+ @media screen and (max-width: 1000px) {
71
+ .sidekiq-scheduler .column-2,
72
+ .sidekiq-scheduler .column-3,
73
+ .sidekiq-scheduler .description {
74
+ width: 100%;
75
+ padding: 5px 10px;
76
+ }
77
+
78
+ .sidekiq-scheduler .queue {
79
+ text-align: left;
80
+ }
81
+ }
@@ -24,6 +24,9 @@
24
24
  color: white;
25
25
  border: 1px solid #555;
26
26
  }
27
+ .list-group-item-disabled {
28
+ color: #585454;
29
+ }
27
30
  }
28
31
 
29
32
  .toggle-all-buttons {
data/web/locales/fr.yml CHANGED
@@ -7,7 +7,10 @@ fr:
7
7
  queue: Queue
8
8
  arguments: Arguments
9
9
  enqueue_now: Ajouter à la queue
10
- next_time: Quand
10
+ last_time: Dernière fois
11
+ next_time: Prochaine fois
11
12
  no_next_time: Pas d'exécution prévue pour cette tâche
12
13
  disable: Désactiver
13
14
  enable: Activer
15
+ disable_all: Tout désactiver
16
+ enable_all: Tout activer
@@ -0,0 +1,16 @@
1
+ gd:
2
+ recurring_jobs: Obraichean ath-chùrsach
3
+ name: Ainm
4
+ description: Tuairisgeul
5
+ interval: Eadaramh
6
+ class: Clas
7
+ queue: Ciudha
8
+ arguments: Argamaidean
9
+ enqueue_now: Cuir sa chiudha an-dràsta
10
+ last_time: An t-àm mu dheireadh
11
+ next_time: An t-ath-àm
12
+ no_next_time: chan eil ath-ghnìomhachadh aig an obair seo
13
+ disable: Cuir à comas
14
+ enable: Cuir an comas
15
+ disable_all: Cuir na h-uile à comas
16
+ enable_all: Cuir na h-uile an comas
@@ -1,93 +1,55 @@
1
- <%# This view is a copy from the sidekiq web view, with just a few new actions (remove, edit, new) %>
2
- <% if Sidekiq::VERSION >= '6.0.0' %>
3
- <link href="<%= root_path %>stylesheets-scheduler/recurring_jobs.css" media="screen" rel="stylesheet" type="text/css" />
4
- <% else %>
5
- <style>
6
- .recurring-jobs { border-top-left-radius: 4px; border-top-right-radius: 4px; }
7
- .recurring-jobs .title { margin-bottom: 5px; }
8
- .recurring-jobs .title .name { font-weight: bold;}
9
- .recurring-jobs .info,
10
- .recurring-jobs .description { margin-bottom: 5px; }
11
- .recurring-jobs .actions { margin-bottom: 5px; }
12
- .recurring-jobs .status,
13
- .recurring-jobs .description { font-size: 12px; }
14
- .recurring-jobs .enqueue { margin-bottom: 0.5rem }
1
+ <% style_tag "recurring_jobs/stylesheets-scheduler/recurring_jobs.css" %>
15
2
 
16
- .list-group-item {
17
- background-color: #f3f3f3;
18
- color: #585454;
19
- border: 1px solid rgba(0, 0, 0, 0.1);
20
- }
21
-
22
- .list-group-item-disabled {
23
- background-color: #f3d3d3;
24
- }
25
-
26
- .toggle-all-buttons {
27
- margin-top: 20px;
28
- margin-bottom: 10px;
29
- line-height: 45px;
30
- text-align: right;
31
- }
32
-
33
- @media (max-width: 768px) {
34
- .toggle-all-buttons {
35
- margin-top: 0;
36
- text-align: left;
37
- line-height: inherit;
38
- }
39
- }
40
- </style>
41
- <% end %>
42
-
43
- <div class="row">
44
- <div class="col-sm-6">
45
- <h3><%= t('recurring_jobs') %></h3>
46
- </div>
47
- <div class="col-sm-6 toggle-all-buttons">
48
- <form action="<%= root_path %>recurring-jobs/toggle-all" method="post">
49
- <%= csrf_tag %>
50
- <button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('enable_all') %></button>
51
- <button type="submit" class="btn btn-warn btn-xs" name="action" value="disable"><%= t('disable_all') %></button>
52
- </form>
53
- <form action="<%= root_path %>recurring-jobs/new" method="post">
54
- <%= csrf_tag %>
55
- <button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('new') %></button>
56
- </form>
57
- </div>
58
- </div>
3
+ <section class="sidekiq-scheduler">
4
+ <header>
5
+ <h2><%= t('recurring_jobs') %></h2>
6
+ <div class="col-sm-6 toggle-all-buttons">
7
+ <form action="<%= root_path %>recurring-jobs/toggle-all" method="POST" class="filter">
8
+ <%= csrf_tag %>
9
+ <div class="btn-group pull-right flip">
10
+ <button type="submit" class="btn btn-xs btn-warn" name="action" value="enable"><%= t('enable_all') %></button>
11
+ <button type="submit" class="btn btn-xs btn-warn" name="action" value="disable"><%= t('disable_all') %></button>
12
+ </div>
13
+ </form>
14
+ <form action="<%= root_path %>recurring-jobs/new" method="post">
15
+ <%= csrf_tag %>
16
+ <button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('new') %></button>
17
+ </form>
18
+ </div>
19
+ </header>
59
20
 
60
- <div class="recurring-jobs">
61
- <ul class="list-group">
21
+ <section class="job-list">
62
22
  <% @presented_jobs.each do |job| %>
63
- <li class="list-group-item <%= !job.enabled? && "list-group-item-disabled" %>">
64
- <div class="title">
65
- <div class="row">
66
- <div class="col-xs-6">
67
- <span class="name"><%= job.name %></span>
68
- </div>
69
- <div class="col-xs-6 text-right">
70
- <a href="<%= root_path %>queues/<%= job.queue %>"><%= job.queue %></a>
71
- </div>
23
+ <section class="job <%= job.enabled? ? "" : "disabled-job" %>">
24
+ <div class="row">
25
+ <div class="column-2">
26
+ <div class="job-name"><%= job.name %></div>
27
+ </div>
28
+ <div class="column-2 queue">
29
+ <a href="<%= root_path %>queues/<%= job.queue %>"><%= job.queue %></a>
72
30
  </div>
73
31
  </div>
74
- <div class="description"><%= job['description'] %></div>
75
- <div class="info">
76
- <div class="row">
77
- <div class="col-md-4 class"><%= job['class'] %></div>
78
- <div class="col-md-4 interval text-left"><%= t('interval') %>: <%= job.interval %></div>
79
- <div class="col-md-4 args"><%= t('arguments') %>: <%= job['args'] %></div>
32
+
33
+ <div class="row">
34
+ <div class="column-3">
35
+ <div class="class-name"><%= job['class'] %></div>
36
+ </div>
37
+ <div class="column-3">
38
+ <div><%= t('interval') %>: <%= job.interval %></div>
39
+ </div>
40
+ <div class="column-3">
41
+ <div><%= t('arguments') %>: <%= job['args'] %></div>
80
42
  </div>
81
43
  </div>
82
- <div class="status row">
83
- <div class="col-md-4 actions">
84
- <form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/enqueue" method="post" class="enqueue">
44
+ <div class="row">
45
+ <div class="column-3">
46
+ <form class="inline" action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/enqueue" method="POST">
85
47
  <%= csrf_tag %>
86
48
  <input type="submit" class="btn btn-warn btn-xs" value="<%= t('enqueue_now') %>" />
87
49
  </form>
88
- <form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/toggle" method="post">
50
+ <form class="inline" action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/toggle" method="POST">
89
51
  <%= csrf_tag %>
90
- <input type="submit" class="btn <%= job.enabled? ? "btn-primary" : "btn-warn"%> btn-xs" value="<%= job.enabled? ? t('disable') : t('enable') %>" />
52
+ <input type="submit" class="btn btn-xs <%= job.enabled? ? "btn-inverse" : "btn-warn"%>" value="<%= job.enabled? ? t('disable') : t('enable') %>" />
91
53
  </form>
92
54
  <form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/destroy" method="post">
93
55
  <%= csrf_tag %>
@@ -98,16 +60,17 @@
98
60
  <input type="submit" class="btn <%= job.enabled? ? "btn-primary" : "btn-warn"%> btn-xs" value="<%= t('edit') %>" />
99
61
  </form>
100
62
  </div>
101
- <div class="col-md-4">
102
- <span class="last_time"><%= t('last_time') %>: <%= job.last_time %></span>
63
+ <div class="column-3">
64
+ <div class="last-time"><%= t('last_time') %>: <%= job.last_time %></div>
103
65
  </div>
104
- <div class="col-md-4">
105
- <span class="next_time text-right" style="<%= 'text-decoration:line-through' unless job.enabled? %>">
106
- <%= t('next_time') %>: <%= job.next_time || t('no_next_time') %>
107
- </span>
66
+ <div class="column-3">
67
+ <div class="next-time"><%= t('next_time') %>: <%= job.next_time || t('no_next_time') %></div>
108
68
  </div>
69
+
109
70
  </div>
110
- </li>
71
+ <div class="description"><%= job['description'] %></div>
72
+
73
+ </section>
111
74
  <% end %>
112
- </ul>
113
- </div>
75
+ </section>
76
+ </section>
@@ -0,0 +1,61 @@
1
+ <%= style_tag "recurring_jobs/stylesheets-scheduler/recurring_jobs_73.css" %>
2
+
3
+ <div class="row">
4
+ <div class="col-sm-6">
5
+ <h3><%= t('recurring_jobs') %></h3>
6
+ </div>
7
+ <div class="col-sm-6 toggle-all-buttons">
8
+ <form action="<%= root_path %>recurring-jobs/toggle-all" method="post">
9
+ <%= csrf_tag %>
10
+ <button type="submit" class="btn btn-warn btn-xs" name="action" value="enable"><%= t('enable_all') %></button>
11
+ <button type="submit" class="btn btn-warn btn-xs" name="action" value="disable"><%= t('disable_all') %></button>
12
+ </form>
13
+ </div>
14
+ </div>
15
+
16
+ <div class="recurring-jobs">
17
+ <ul class="list-group">
18
+ <% @presented_jobs.each do |job| %>
19
+ <li class="list-group-item <%= !job.enabled? && "list-group-item-disabled" %>">
20
+ <div class="title">
21
+ <div class="row">
22
+ <div class="col-xs-6">
23
+ <span class="name"><%= job.name %></span>
24
+ </div>
25
+ <div class="col-xs-6 text-right">
26
+ <a href="<%= root_path %>queues/<%= job.queue %>"><%= job.queue %></a>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ <div class="description"><%= job['description'] %></div>
31
+ <div class="info">
32
+ <div class="row">
33
+ <div class="col-md-4 class"><%= job['class'] %></div>
34
+ <div class="col-md-4 interval text-left"><%= t('interval') %>: <%= job.interval %></div>
35
+ <div class="col-md-4 args"><%= t('arguments') %>: <%= job['args'] %></div>
36
+ </div>
37
+ </div>
38
+ <div class="status row">
39
+ <div class="col-md-4 actions">
40
+ <form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/enqueue" method="post" class="enqueue">
41
+ <%= csrf_tag %>
42
+ <input type="submit" class="btn btn-warn btn-xs" value="<%= t('enqueue_now') %>" />
43
+ </form>
44
+ <form action="<%= root_path %>recurring-jobs/<%= ERB::Util.url_encode(job.name) %>/toggle" method="post">
45
+ <%= csrf_tag %>
46
+ <input type="submit" class="btn <%= job.enabled? ? "btn-primary" : "btn-warn"%> btn-xs" value="<%= job.enabled? ? t('disable') : t('enable') %>" />
47
+ </form>
48
+ </div>
49
+ <div class="col-md-4">
50
+ <span class="last_time"><%= t('last_time') %>: <%= job.last_time %></span>
51
+ </div>
52
+ <div class="col-md-4">
53
+ <span class="next_time text-right" style="<%= 'text-decoration:line-through' unless job.enabled? %>">
54
+ <%= t('next_time') %>: <%= job.next_time || t('no_next_time') %>
55
+ </span>
56
+ </div>
57
+ </div>
58
+ </li>
59
+ <% end %>
60
+ </ul>
61
+ </div>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamodb-sidekiq-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: '0.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Morton Jonuschat
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-05-25 00:00:00.000000000 Z
13
+ date: 2026-05-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sidekiq
@@ -18,20 +18,20 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '6'
21
+ version: '7.3'
22
22
  - - "<"
23
23
  - !ruby/object:Gem::Version
24
- version: '8'
24
+ version: '9'
25
25
  type: :runtime
26
26
  prerelease: false
27
27
  version_requirements: !ruby/object:Gem::Requirement
28
28
  requirements:
29
29
  - - ">="
30
30
  - !ruby/object:Gem::Version
31
- version: '6'
31
+ version: '7.3'
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
- version: '8'
34
+ version: '9'
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rufus-scheduler
37
37
  requirement: !ruby/object:Gem::Requirement
@@ -46,20 +46,6 @@ dependencies:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
48
  version: '3.2'
49
- - !ruby/object:Gem::Dependency
50
- name: tilt
51
- requirement: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: 1.4.0
56
- type: :runtime
57
- prerelease: false
58
- version_requirements: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 1.4.0
63
49
  - !ruby/object:Gem::Dependency
64
50
  name: rake
65
51
  requirement: !ruby/object:Gem::Requirement
@@ -164,28 +150,14 @@ dependencies:
164
150
  requirements:
165
151
  - - ">="
166
152
  - !ruby/object:Gem::Version
167
- version: '0'
153
+ version: '1.1'
168
154
  type: :development
169
155
  prerelease: false
170
156
  version_requirements: !ruby/object:Gem::Requirement
171
157
  requirements:
172
158
  - - ">="
173
159
  - !ruby/object:Gem::Version
174
- version: '0'
175
- - !ruby/object:Gem::Dependency
176
- name: rack
177
- requirement: !ruby/object:Gem::Requirement
178
- requirements:
179
- - - "<"
180
- - !ruby/object:Gem::Version
181
- version: '3'
182
- type: :development
183
- prerelease: false
184
- version_requirements: !ruby/object:Gem::Requirement
185
- requirements:
186
- - - "<"
187
- - !ruby/object:Gem::Version
188
- version: '3'
160
+ version: '1.1'
189
161
  description: Light weight job scheduling extension for Sidekiq that adds support for
190
162
  queueing jobs in a recurring way.
191
163
  email:
@@ -214,12 +186,14 @@ files:
214
186
  - lib/sidekiq-scheduler/version.rb
215
187
  - lib/sidekiq-scheduler/web.rb
216
188
  - lib/sidekiq/scheduler.rb
217
- - web/assets/stylesheets-scheduler/recurring_jobs.css
189
+ - web/assets/recurring_jobs/stylesheets-scheduler/recurring_jobs.css
190
+ - web/assets/recurring_jobs/stylesheets-scheduler/recurring_jobs_73.css
218
191
  - web/locales/cs.yml
219
192
  - web/locales/de.yml
220
193
  - web/locales/en.yml
221
194
  - web/locales/es.yml
222
195
  - web/locales/fr.yml
196
+ - web/locales/gd.yml
223
197
  - web/locales/it.yml
224
198
  - web/locales/ja.yml
225
199
  - web/locales/nl.yml
@@ -230,10 +204,15 @@ files:
230
204
  - web/locales/zh-cn.yml
231
205
  - web/views/recurring_job.erb
232
206
  - web/views/recurring_jobs.erb
207
+ - web/views/sidekiq73/recurring_jobs.erb
233
208
  homepage: https://sidekiq-scheduler.github.io/sidekiq-scheduler/
234
209
  licenses:
235
210
  - MIT
236
- metadata: {}
211
+ metadata:
212
+ rubygems_mfa_required: 'true'
213
+ source_code_uri: https://github.com/sidekiq-scheduler/sidekiq-scheduler
214
+ bug_tracker_uri: https://github.com/sidekiq-scheduler/sidekiq-scheduler/issues
215
+ changelog_uri: https://github.com/sidekiq-scheduler/sidekiq-scheduler/blob/master/CHANGELOG.md
237
216
  post_install_message:
238
217
  rdoc_options: []
239
218
  require_paths:
@@ -249,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
228
  - !ruby/object:Gem::Version
250
229
  version: '0'
251
230
  requirements: []
252
- rubygems_version: 3.1.6
231
+ rubygems_version: 3.3.7
253
232
  signing_key:
254
233
  specification_version: 4
255
234
  summary: Light weight job scheduling extension for Sidekiq