sidekiq-defer 1.0.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 +7 -0
- data/Changes.md +43 -0
- data/LICENSE +9 -0
- data/README.md +115 -0
- data/lib/sidekiq/defer/action_mailer.rb +47 -0
- data/lib/sidekiq/defer/active_record.rb +44 -0
- data/lib/sidekiq/defer/api.rb +48 -0
- data/lib/sidekiq/defer/class_methods.rb +44 -0
- data/lib/sidekiq/defer/generic_proxy.rb +56 -0
- data/lib/sidekiq/defer/testing.rb +24 -0
- data/lib/sidekiq/defer/version.rb +7 -0
- data/lib/sidekiq/defer.rb +84 -0
- data/lib/sidekiq/delay_extensions.rb +3 -0
- data/sidekiq-defer.gemspec +35 -0
- metadata +81 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a65a0f7cbd6662bd9c552c3f5ae062297a09043c34a4616d6a811e860fc77fc5
|
|
4
|
+
data.tar.gz: 39de49a6c7e84a573f68eb01f6e3c62ca1ac0fe5edf9e9310edd124aa9afdd83
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 51289603549d4c4283ed6a3768964360d409ac7753e05a9ab1651c0fb7907a0d3ee14c2511f1c693aa25584cdf5286a0555af5eb7f7a9570849e566a36640d38
|
|
7
|
+
data.tar.gz: 12f72295a1ff9bb9da191585bdf8d8c9dbe3c35e3a4770e3f8a5c0775817323443ace93bc9607b4cd4b19dd6889b8cb3aca5fbd7febb58e69460839ee500767d
|
data/Changes.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# sidekiq-defer Changes
|
|
2
|
+
|
|
3
|
+
1.0.0
|
|
4
|
+
---------
|
|
5
|
+
|
|
6
|
+
First release under its own version line; use this instead of 9.0.0.
|
|
7
|
+
|
|
8
|
+
- Jobs are named after their target in Sidekiq metrics, job logs and Sentry: the target's class
|
|
9
|
+
name is stored in the job's `wrapped` key (`wrap_target: false` turns it off).
|
|
10
|
+
- Fix: 9.0.0 pushed `Foo::DeferredJob`, which was only defined in the process that called
|
|
11
|
+
`Foo.delay`, so Sidekiq servers failed with `NameError`. Jobs run through the shared
|
|
12
|
+
`Sidekiq::Defer::DelayedClass` / `DelayedModel` / `DelayedMailer` again.
|
|
13
|
+
- Fix: the Web UI showed raw YAML arguments for `Sidekiq::Defer::Delayed*` jobs.
|
|
14
|
+
- Fix: delayed mailer methods receive keyword arguments.
|
|
15
|
+
- `legacy_class_names: true` pushes `Sidekiq::DelayExtensions::Delayed*` for rolling deploys from
|
|
16
|
+
`sidekiq-delay_extensions`.
|
|
17
|
+
- `Proxy#build_item` hook for adding keys to the job hash.
|
|
18
|
+
- `Sidekiq::Defer::DelayedClass` gets `jobs_for` under `Sidekiq::Testing`.
|
|
19
|
+
- Requires Sidekiq >= 7.0, < 9. Packages only files committed to git. Release tasks in `rakelib/release.rake`.
|
|
20
|
+
- Lint with RuboCop (single quotes) instead of StandardRB.
|
|
21
|
+
- Renamed gem to `sidekiq-defer`
|
|
22
|
+
- Module renamed from `Sidekiq::DelayExtensions` to `Sidekiq::Delay`
|
|
23
|
+
- `Sidekiq::DelayExtensions` kept as a backward-compatible alias
|
|
24
|
+
|
|
25
|
+
8.0.0
|
|
26
|
+
---------
|
|
27
|
+
|
|
28
|
+
- Support sidekiq v8.0+
|
|
29
|
+
|
|
30
|
+
7.0.0
|
|
31
|
+
---------
|
|
32
|
+
|
|
33
|
+
- Support sidekiq v6.5+
|
|
34
|
+
|
|
35
|
+
6.4.1
|
|
36
|
+
---------
|
|
37
|
+
|
|
38
|
+
- Extracted from https://github.com/mperham/sidekiq/tree/v6.4.1
|
|
39
|
+
|
|
40
|
+
6.4.0
|
|
41
|
+
---------
|
|
42
|
+
|
|
43
|
+
- Extracted from https://github.com/mperham/sidekiq/tree/v6.4.0
|
data/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Copyright (c) Contributed Systems LLC
|
|
2
|
+
|
|
3
|
+
Sidekiq is an Open Source project licensed under the terms of
|
|
4
|
+
the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
|
|
5
|
+
for license text.
|
|
6
|
+
|
|
7
|
+
Sidekiq Pro and Sidekiq Enterprise have a commercial-friendly license.
|
|
8
|
+
You can find the commercial license in COMM-LICENSE.txt.
|
|
9
|
+
Please see https://sidekiq.org for purchasing options.
|
data/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
sidekiq-defer
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
[](https://rubygems.org/gems/sidekiq-defer)
|
|
5
|
+
|
|
6
|
+
The Sidekiq delay extensions were removed in Sidekiq 7.x. This gem restores them for apps still relying on the `delay`/`delay_for`/`delay_until` pattern.
|
|
7
|
+
|
|
8
|
+
Requirements
|
|
9
|
+
-----------------
|
|
10
|
+
|
|
11
|
+
- Redis: 6.2+
|
|
12
|
+
- Ruby: MRI 3.2+
|
|
13
|
+
- Sidekiq 7.0+ (< 9)
|
|
14
|
+
|
|
15
|
+
Installation
|
|
16
|
+
-----------------
|
|
17
|
+
|
|
18
|
+
gem 'sidekiq-defer', '~> 1.0'
|
|
19
|
+
|
|
20
|
+
In your initializer:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
Sidekiq::Defer.enable_delay!
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then any class, ActiveRecord model or mailer can run a method in the background:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
Report.delay.export(account_id)
|
|
30
|
+
Report.delay_for(10.minutes, queue: :low).export(account_id)
|
|
31
|
+
UserMailer.delay_until(1.day.from_now).welcome(user_id)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
|
|
36
|
+
| Option | Default | |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `limit_payload_size:` | `false` | `true` (8 KB) or a byte count: log a warning when the YAML payload is larger. |
|
|
39
|
+
| `wrap_target:` | `true` | Name the job after its target in metrics, logs and error reports (see below). |
|
|
40
|
+
| `legacy_class_names:` | `false` | Push jobs as `Sidekiq::DelayExtensions::Delayed*` (see upgrading). |
|
|
41
|
+
|
|
42
|
+
Metrics and naming
|
|
43
|
+
-----------------
|
|
44
|
+
|
|
45
|
+
Every delayed call runs through one of three job classes: `Sidekiq::Defer::DelayedClass`,
|
|
46
|
+
`DelayedModel` and `DelayedMailer`. The gem also stores the target's class name in the job's
|
|
47
|
+
`wrapped` key, as ActiveJob does. Sidekiq reads `wrapped` first, so `Report.delay.export` is listed
|
|
48
|
+
as `Report` on the Metrics page, in the job logger's `class` field, and in Sentry transaction names.
|
|
49
|
+
The Web UI shows `Report.export` and the original arguments.
|
|
50
|
+
|
|
51
|
+
`wrapped` is a class name, never `Report.export`: Sidekiq's retry handler resolves it with
|
|
52
|
+
`const_get`. If the target is itself a Sidekiq job class, its `sidekiq_retry_in` and
|
|
53
|
+
`sidekiq_retries_exhausted` blocks apply to the delayed call. To extend the job hash, prepend a
|
|
54
|
+
module that overrides `Sidekiq::Defer::Proxy#build_item`, or use Sidekiq client middleware.
|
|
55
|
+
|
|
56
|
+
Upgrading from `sidekiq-delay_extensions`
|
|
57
|
+
-----------------
|
|
58
|
+
|
|
59
|
+
`Sidekiq::DelayExtensions` and `Sidekiq::TestingDelayExtensions` are aliases of the new names,
|
|
60
|
+
so existing code and jobs already in Redis keep working.
|
|
61
|
+
|
|
62
|
+
New jobs are pushed as `Sidekiq::Defer::Delayed*`, which processes still running
|
|
63
|
+
`sidekiq-delay_extensions` can't resolve. For a rolling deploy:
|
|
64
|
+
|
|
65
|
+
1. Deploy with `Sidekiq::Defer.enable_delay!(legacy_class_names: true)`. Jobs keep the old class
|
|
66
|
+
name but already get the `wrapped` name.
|
|
67
|
+
2. Once every process runs `sidekiq-defer`, remove `legacy_class_names: true`.
|
|
68
|
+
|
|
69
|
+
Under `Sidekiq::Testing`, the current class names are always used, so `Sidekiq::Defer::DelayedClass.jobs` works.
|
|
70
|
+
|
|
71
|
+
Upgrading from Sidekiq's built-in extensions
|
|
72
|
+
-----------------
|
|
73
|
+
|
|
74
|
+
Jobs already in Redis were serialized with the old class names. Add these aliases so they can still be processed:
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
Sidekiq::Extensions::DelayedClass = Sidekiq::Defer::DelayedClass
|
|
78
|
+
Sidekiq::Extensions::DelayedModel = Sidekiq::Defer::DelayedModel
|
|
79
|
+
Sidekiq::Extensions::DelayedMailer = Sidekiq::Defer::DelayedMailer
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Testing
|
|
83
|
+
-----------------
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
require 'sidekiq/defer/testing'
|
|
87
|
+
|
|
88
|
+
Report.delay.export(1)
|
|
89
|
+
Sidekiq::Defer::DelayedClass.jobs.size # => 1
|
|
90
|
+
Sidekiq::Defer::DelayedClass.jobs_for(Report) # jobs whose target is Report
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Releasing
|
|
94
|
+
-----------------
|
|
95
|
+
|
|
96
|
+
rake "release:bump[minor]" # bump version.rb, add a Changes.md section
|
|
97
|
+
rake release:dry_run # checks, lint, tests, package inspection; pushes nothing
|
|
98
|
+
rake release # the same checks, then tag vX.Y.Z and push to rubygems.org
|
|
99
|
+
|
|
100
|
+
Contributing
|
|
101
|
+
-----------------
|
|
102
|
+
|
|
103
|
+
Please open issues or pull requests at https://github.com/moskvin/sidekiq-delay_extensions.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
License
|
|
107
|
+
-----------------
|
|
108
|
+
|
|
109
|
+
Please see [LICENSE](https://github.com/moskvin/sidekiq-delay_extensions/blob/sidekiq8/LICENSE) for licensing details.
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
Original Author
|
|
113
|
+
-----------------
|
|
114
|
+
|
|
115
|
+
Mike Perham, [@getajobmike](https://twitter.com/getajobmike) / [@sidekiq](https://twitter.com/sidekiq), [https://www.mikeperham.com](https://www.mikeperham.com) / [https://www.contribsys.com](https://www.contribsys.com)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sidekiq/defer/generic_proxy'
|
|
4
|
+
|
|
5
|
+
module Sidekiq
|
|
6
|
+
module Defer
|
|
7
|
+
##
|
|
8
|
+
# Adds +delay+, +delay_for+ and +delay_until+ methods to ActionMailer to offload arbitrary email
|
|
9
|
+
# delivery to Sidekiq.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# UserMailer.delay.send_welcome_email(new_user)
|
|
13
|
+
# UserMailer.delay_for(5.days).send_welcome_email(new_user)
|
|
14
|
+
# UserMailer.delay_until(5.days.from_now).send_welcome_email(new_user)
|
|
15
|
+
class DelayedMailer
|
|
16
|
+
include Sidekiq::Job
|
|
17
|
+
|
|
18
|
+
def perform(yml)
|
|
19
|
+
(target, method_name, args, kwargs) = YAML.safe_load(yml, permitted_classes: [Symbol])
|
|
20
|
+
msg = target.public_send(method_name, *args, **kwargs.to_h)
|
|
21
|
+
# The email method can return nil, which causes ActionMailer to return
|
|
22
|
+
# an undeliverable empty message.
|
|
23
|
+
raise "#{target.name}##{method_name} returned an undeliverable mail object" unless msg
|
|
24
|
+
|
|
25
|
+
msg.deliver_now
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module ActionMailer
|
|
30
|
+
def sidekiq_delay(**)
|
|
31
|
+
Proxy.new(DelayedMailer, self, **)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def sidekiq_delay_for(interval, **)
|
|
35
|
+
Proxy.new(DelayedMailer, self, **, at: Time.now.to_f + interval.to_f)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def sidekiq_delay_until(timestamp, **)
|
|
39
|
+
Proxy.new(DelayedMailer, self, **, at: timestamp.to_f)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
alias delay sidekiq_delay
|
|
43
|
+
alias delay_for sidekiq_delay_for
|
|
44
|
+
alias delay_until sidekiq_delay_until
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sidekiq/defer/generic_proxy'
|
|
4
|
+
|
|
5
|
+
module Sidekiq
|
|
6
|
+
module Defer
|
|
7
|
+
##
|
|
8
|
+
# Adds +delay+, +delay_for+ and +delay_until+ methods to ActiveRecord to offload instance method
|
|
9
|
+
# execution to Sidekiq.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# User.recent_signups.each { |user| user.delay.mark_as_awesome }
|
|
13
|
+
#
|
|
14
|
+
# Please note, this is not recommended as this will serialize the entire
|
|
15
|
+
# object to Redis. Your Sidekiq jobs should pass IDs, not entire instances.
|
|
16
|
+
# This is here for backwards compatibility with Delayed::Job only.
|
|
17
|
+
class DelayedModel
|
|
18
|
+
include Sidekiq::Job
|
|
19
|
+
|
|
20
|
+
def perform(yml)
|
|
21
|
+
(target, method_name, args, kwargs) = YAML.safe_load(yml, permitted_classes: [Symbol])
|
|
22
|
+
target.__send__(method_name, *args, **kwargs.to_h)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module ActiveRecord
|
|
27
|
+
def sidekiq_delay(**)
|
|
28
|
+
Proxy.new(DelayedModel, self, **)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def sidekiq_delay_for(interval, **)
|
|
32
|
+
Proxy.new(DelayedModel, self, **, at: Time.now.to_f + interval.to_f)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def sidekiq_delay_until(timestamp, **)
|
|
36
|
+
Proxy.new(DelayedModel, self, **, at: timestamp.to_f)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
alias delay sidekiq_delay
|
|
40
|
+
alias delay_for sidekiq_delay_for
|
|
41
|
+
alias delay_until sidekiq_delay_until
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sidekiq/api'
|
|
4
|
+
|
|
5
|
+
module Sidekiq
|
|
6
|
+
module Defer
|
|
7
|
+
# Current, pre-rename and Sidekiq 6 built-in names, plus 9.0.0 per-target classes.
|
|
8
|
+
DELAYED_JOB_PATTERN = /\ASidekiq::(?:Defer|DelayExtensions|Delay|Extensions)::Delayed|::DeferredJob\z/
|
|
9
|
+
|
|
10
|
+
module JobRecord
|
|
11
|
+
def display_class
|
|
12
|
+
# Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
|
|
13
|
+
@display_class ||= self['display_class'] || begin
|
|
14
|
+
case klass
|
|
15
|
+
when DELAYED_JOB_PATTERN
|
|
16
|
+
safe_load(args[0], klass) do |target, method, _|
|
|
17
|
+
"#{target}.#{method}"
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def display_args
|
|
26
|
+
# Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
|
|
27
|
+
@display_args ||= case klass
|
|
28
|
+
when DELAYED_JOB_PATTERN
|
|
29
|
+
safe_load(args[0], args) do |_, _, arg, kwargs|
|
|
30
|
+
if !kwargs || kwargs.empty?
|
|
31
|
+
arg
|
|
32
|
+
else
|
|
33
|
+
[arg, kwargs]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def safe_load(content, _default)
|
|
44
|
+
yield(*YAML.safe_load(content, permitted_classes: [Symbol]))
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sidekiq/defer/generic_proxy'
|
|
4
|
+
|
|
5
|
+
module Sidekiq
|
|
6
|
+
module Defer
|
|
7
|
+
##
|
|
8
|
+
# Adds `delay`, `delay_for` and `delay_until` methods to all Classes to offload class method
|
|
9
|
+
# execution to Sidekiq.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# User.delay.delete_inactive
|
|
13
|
+
# Wikipedia.delay.download_changes_for(Date.today)
|
|
14
|
+
#
|
|
15
|
+
class DelayedClass
|
|
16
|
+
include Sidekiq::Job
|
|
17
|
+
|
|
18
|
+
def perform(yml)
|
|
19
|
+
(target, method_name, args, kwargs) = YAML.safe_load(yml, permitted_classes: [Symbol])
|
|
20
|
+
target.__send__(method_name, *args, **kwargs)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module Klass
|
|
25
|
+
def sidekiq_delay(**)
|
|
26
|
+
Proxy.new(DelayedClass, self, **)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def sidekiq_delay_for(interval, **)
|
|
30
|
+
Proxy.new(DelayedClass, self, **, at: Time.now.to_f + interval.to_f)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def sidekiq_delay_until(timestamp, **)
|
|
34
|
+
Proxy.new(DelayedClass, self, **, at: timestamp.to_f)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
alias delay sidekiq_delay
|
|
38
|
+
alias delay_for sidekiq_delay_for
|
|
39
|
+
alias delay_until sidekiq_delay_until
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Module.include Sidekiq::Defer::Klass unless defined?(Rails)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
module Sidekiq
|
|
6
|
+
module Defer
|
|
7
|
+
DEFAULT_SIZE_LIMIT = 8_192
|
|
8
|
+
|
|
9
|
+
class Proxy < BasicObject
|
|
10
|
+
def initialize(performable, target, **options)
|
|
11
|
+
@performable = performable
|
|
12
|
+
@target = target
|
|
13
|
+
@opts = options.transform_keys(&:to_s)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def respond_to_missing?(_name, _include_private = false)
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def method_missing(name, *args, **kwargs)
|
|
21
|
+
# Sidekiq has a limitation in that its message must be JSON.
|
|
22
|
+
# JSON can't round trip real Ruby objects so we use YAML to
|
|
23
|
+
# serialize the objects to a String. The YAML will be converted
|
|
24
|
+
# to JSON and then deserialized on the other side back into a
|
|
25
|
+
# Ruby object.
|
|
26
|
+
obj = [@target, name, args, kwargs]
|
|
27
|
+
marshalled = ::YAML.dump(obj)
|
|
28
|
+
print_warning(name, marshalled)
|
|
29
|
+
|
|
30
|
+
@performable.client_push(build_item(name, marshalled))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The job hash pushed to Sidekiq. Override (e.g. with prepend) to add keys.
|
|
34
|
+
def build_item(name, marshalled)
|
|
35
|
+
item = { 'class' => ::Sidekiq::Defer.job_class_name(@performable),
|
|
36
|
+
'args' => [marshalled],
|
|
37
|
+
'display_class' => "#{@target}.#{name}" }
|
|
38
|
+
wrapped = ::Sidekiq::Defer.wrapped_name(@target)
|
|
39
|
+
item['wrapped'] = wrapped if wrapped
|
|
40
|
+
item.merge(@opts)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def print_warning(name, dump)
|
|
44
|
+
limited_payload_size = Defer.limit_payload_size
|
|
45
|
+
return unless limited_payload_size
|
|
46
|
+
|
|
47
|
+
size = limited_payload_size == true ? DEFAULT_SIZE_LIMIT : limited_payload_size
|
|
48
|
+
return if dump.bytesize <= size
|
|
49
|
+
|
|
50
|
+
::Sidekiq.logger.warn do
|
|
51
|
+
"#{@target}.#{name} job argument is #{dump.bytesize} bytes, you should refactor it to reduce the size"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sidekiq/testing'
|
|
4
|
+
|
|
5
|
+
module Sidekiq
|
|
6
|
+
module TestingDefer
|
|
7
|
+
def jobs_for(klass)
|
|
8
|
+
jobs.select do |job|
|
|
9
|
+
marshalled = job['args'][0]
|
|
10
|
+
marshalled.index(klass.to_s) && YAML.safe_load(marshalled, permitted_classes: [Symbol])[0] == klass
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.enable_delay_testing!
|
|
15
|
+
Sidekiq::Defer::DelayedClass.extend(TestingDefer) if defined?(Sidekiq::Defer::DelayedClass)
|
|
16
|
+
Sidekiq::Defer::DelayedMailer.extend(TestingDefer) if defined?(Sidekiq::Defer::DelayedMailer)
|
|
17
|
+
Sidekiq::Defer::DelayedModel.extend(TestingDefer) if defined?(Sidekiq::Defer::DelayedModel)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
TestingDefer.enable_delay_testing!
|
|
22
|
+
|
|
23
|
+
TestingDelayExtensions = TestingDefer
|
|
24
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sidekiq'
|
|
4
|
+
require 'sidekiq/defer/version'
|
|
5
|
+
|
|
6
|
+
module Sidekiq
|
|
7
|
+
module Defer
|
|
8
|
+
# Namespace the job classes lived in before the rename. Jobs already in Redis
|
|
9
|
+
# reference it, and it resolves through the DelayExtensions alias below.
|
|
10
|
+
LEGACY_NAMESPACE = 'Sidekiq::DelayExtensions'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_accessor :limit_payload_size, :wrap_target, :legacy_class_names
|
|
14
|
+
end
|
|
15
|
+
self.wrap_target = true
|
|
16
|
+
self.legacy_class_names = false
|
|
17
|
+
|
|
18
|
+
# wrap_target: store the target's class name in the job's "wrapped" key, which
|
|
19
|
+
# Sidekiq uses to name the job in metrics, logs and error reports.
|
|
20
|
+
# legacy_class_names: push jobs as Sidekiq::DelayExtensions::Delayed*, so processes
|
|
21
|
+
# still running sidekiq-delay_extensions can run them during a rolling deploy.
|
|
22
|
+
def self.enable_delay!(limit_payload_size: false, wrap_target: true, legacy_class_names: false)
|
|
23
|
+
self.limit_payload_size = limit_payload_size
|
|
24
|
+
self.wrap_target = wrap_target
|
|
25
|
+
self.legacy_class_names = legacy_class_names
|
|
26
|
+
if defined?(::ActiveSupport)
|
|
27
|
+
require 'sidekiq/defer/active_record'
|
|
28
|
+
require 'sidekiq/defer/action_mailer'
|
|
29
|
+
|
|
30
|
+
# Need to patch Psych so it can autoload classes whose names are serialized
|
|
31
|
+
# in the delayed YAML.
|
|
32
|
+
Psych::Visitors::ToRuby.prepend(Sidekiq::Defer::PsychAutoload)
|
|
33
|
+
|
|
34
|
+
ActiveSupport.on_load(:active_record) do
|
|
35
|
+
include Sidekiq::Defer::ActiveRecord
|
|
36
|
+
end
|
|
37
|
+
ActiveSupport.on_load(:action_mailer) do
|
|
38
|
+
extend Sidekiq::Defer::ActionMailer
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
require 'sidekiq/defer/class_methods'
|
|
43
|
+
Module.include Sidekiq::Defer::Klass
|
|
44
|
+
|
|
45
|
+
require 'sidekiq/defer/api'
|
|
46
|
+
Sidekiq::JobRecord.prepend(Sidekiq::Defer::JobRecord)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The "class" pushed for a delayed job. Legacy names are skipped under
|
|
50
|
+
# Sidekiq::Testing, which files jobs by class name.
|
|
51
|
+
def self.job_class_name(performable)
|
|
52
|
+
return performable.name unless legacy_class_names
|
|
53
|
+
return performable.name if defined?(::Sidekiq::Testing) && ::Sidekiq::Testing.enabled?
|
|
54
|
+
|
|
55
|
+
"#{LEGACY_NAMESPACE}::#{performable.name.split('::').last}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The "wrapped" value for a delayed job: the target's class name. It must be a
|
|
59
|
+
# constant name, because Sidekiq's retry handler resolves it with const_get.
|
|
60
|
+
def self.wrapped_name(target)
|
|
61
|
+
return unless wrap_target
|
|
62
|
+
|
|
63
|
+
(target.is_a?(::Module) ? target : target.class).name
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
module PsychAutoload
|
|
67
|
+
def resolve_class(klass_name)
|
|
68
|
+
return nil if !klass_name || klass_name.empty?
|
|
69
|
+
|
|
70
|
+
# constantize
|
|
71
|
+
names = klass_name.split('::')
|
|
72
|
+
names.shift if names.empty? || names.first.empty?
|
|
73
|
+
|
|
74
|
+
names.inject(Object) do |constant, name|
|
|
75
|
+
constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
|
76
|
+
end
|
|
77
|
+
rescue NameError
|
|
78
|
+
super
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
DelayExtensions = Defer
|
|
84
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/sidekiq/defer/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'sidekiq-defer'
|
|
7
|
+
spec.version = Sidekiq::Defer::VERSION
|
|
8
|
+
spec.authors = ['Mike Perham', 'Benjamin Fleischer', 'Nikolay Moskvin']
|
|
9
|
+
spec.email = %w[mperham@gmail.com github@benjaminfleischer.com]
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Sidekiq Defer Extensions'
|
|
12
|
+
spec.description = 'Delay extensions for Sidekiq 7+'
|
|
13
|
+
spec.homepage = 'https://github.com/moskvin/sidekiq-delay_extensions'
|
|
14
|
+
spec.license = 'LGPL-3.0-or-later'
|
|
15
|
+
|
|
16
|
+
# Only files committed to git, so a local scratch file can never be published.
|
|
17
|
+
spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, &:read).split("\x0").select do |f|
|
|
18
|
+
f.start_with?('lib/') || %w[Changes.md LICENSE README.md sidekiq-defer.gemspec].include?(f)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
spec.bindir = 'exe'
|
|
22
|
+
spec.executables = []
|
|
23
|
+
spec.require_paths = ['lib']
|
|
24
|
+
spec.required_ruby_version = '>= 3.2.0'
|
|
25
|
+
|
|
26
|
+
spec.metadata = {
|
|
27
|
+
'homepage_uri' => 'https://github.com/moskvin/sidekiq-delay_extensions',
|
|
28
|
+
'bug_tracker_uri' => 'https://github.com/moskvin/sidekiq-delay_extensions/issues',
|
|
29
|
+
'changelog_uri' => 'https://github.com/moskvin/sidekiq-delay_extensions/blob/main/Changes.md',
|
|
30
|
+
'source_code_uri' => 'https://github.com/moskvin/sidekiq-delay_extensions',
|
|
31
|
+
'rubygems_mfa_required' => 'true'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
spec.add_dependency 'sidekiq', '>= 7.0', '< 9'
|
|
35
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: sidekiq-defer
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Mike Perham
|
|
8
|
+
- Benjamin Fleischer
|
|
9
|
+
- Nikolay Moskvin
|
|
10
|
+
bindir: exe
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: sidekiq
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - ">="
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: '7.0'
|
|
21
|
+
- - "<"
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: '9'
|
|
24
|
+
type: :runtime
|
|
25
|
+
prerelease: false
|
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
27
|
+
requirements:
|
|
28
|
+
- - ">="
|
|
29
|
+
- !ruby/object:Gem::Version
|
|
30
|
+
version: '7.0'
|
|
31
|
+
- - "<"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '9'
|
|
34
|
+
description: Delay extensions for Sidekiq 7+
|
|
35
|
+
email:
|
|
36
|
+
- mperham@gmail.com
|
|
37
|
+
- github@benjaminfleischer.com
|
|
38
|
+
executables: []
|
|
39
|
+
extensions: []
|
|
40
|
+
extra_rdoc_files: []
|
|
41
|
+
files:
|
|
42
|
+
- Changes.md
|
|
43
|
+
- LICENSE
|
|
44
|
+
- README.md
|
|
45
|
+
- lib/sidekiq/defer.rb
|
|
46
|
+
- lib/sidekiq/defer/action_mailer.rb
|
|
47
|
+
- lib/sidekiq/defer/active_record.rb
|
|
48
|
+
- lib/sidekiq/defer/api.rb
|
|
49
|
+
- lib/sidekiq/defer/class_methods.rb
|
|
50
|
+
- lib/sidekiq/defer/generic_proxy.rb
|
|
51
|
+
- lib/sidekiq/defer/testing.rb
|
|
52
|
+
- lib/sidekiq/defer/version.rb
|
|
53
|
+
- lib/sidekiq/delay_extensions.rb
|
|
54
|
+
- sidekiq-defer.gemspec
|
|
55
|
+
homepage: https://github.com/moskvin/sidekiq-delay_extensions
|
|
56
|
+
licenses:
|
|
57
|
+
- LGPL-3.0-or-later
|
|
58
|
+
metadata:
|
|
59
|
+
homepage_uri: https://github.com/moskvin/sidekiq-delay_extensions
|
|
60
|
+
bug_tracker_uri: https://github.com/moskvin/sidekiq-delay_extensions/issues
|
|
61
|
+
changelog_uri: https://github.com/moskvin/sidekiq-delay_extensions/blob/main/Changes.md
|
|
62
|
+
source_code_uri: https://github.com/moskvin/sidekiq-delay_extensions
|
|
63
|
+
rubygems_mfa_required: 'true'
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: 3.2.0
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
requirements: []
|
|
78
|
+
rubygems_version: 4.0.20
|
|
79
|
+
specification_version: 4
|
|
80
|
+
summary: Sidekiq Defer Extensions
|
|
81
|
+
test_files: []
|