sidekiq-antidote 1.0.0.alpha.1 → 1.1.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 +4 -4
- data/README.adoc +100 -24
- data/lib/sidekiq/antidote/config.rb +0 -37
- data/lib/sidekiq/antidote/inhibitor.rb +0 -4
- data/lib/sidekiq/antidote/middlewares/client.rb +2 -2
- data/lib/sidekiq/antidote/middlewares/server.rb +2 -2
- data/lib/sidekiq/antidote/middlewares/shared.rb +12 -2
- data/lib/sidekiq/antidote/remedy.rb +4 -4
- data/lib/sidekiq/antidote/repository.rb +4 -9
- data/lib/sidekiq/antidote/version.rb +1 -1
- data/lib/sidekiq/antidote.rb +3 -7
- data/web/locales/en.yml +4 -2
- data/web/views/add.html.erb +45 -20
- data/web/views/index.html.erb +2 -2
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f5bdf47fd299dc626c6fc0afb94896301c66e5b1f9f33875383375d0d5ac483
|
4
|
+
data.tar.gz: bb9966c063f7ca0325d31229c6f4d0cf445d53392bb89a201dba92891759ece3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87e30e47eb2e37cea51f9037469a4395651d49da8664558d893a71e83d7af275c32ea5ce2e6e8c6b6d464e979af684498972dd2a21c5ddedaf9fe73a2e4a1e62
|
7
|
+
data.tar.gz: ffea8f3beef24555534621992e60d18c3c3ec0ab3855e07a65e5a274a434a0285f8442efe851ef8c1377df8f9f72920d290c545b42eb56566c3ee0d53a124362
|
data/README.adoc
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= Sidekiq::Antidote
|
2
2
|
|
3
|
+
:ci-url: https://github.com/ixti/sidekiq-antidote/actions/workflows/ci.yml?query=branch%3Amain
|
4
|
+
:ci-img: https://github.com/ixti/sidekiq-antidote/actions/workflows/ci.yml/badge.svg?branch=main
|
5
|
+
:codecov-url: https://codecov.io/gh/ixti/sidekiq-antidote/tree/main
|
6
|
+
:codecov-img: https://codecov.io/gh/ixti/sidekiq-antidote/graph/badge.svg?token=F5AAMPN35A
|
7
|
+
|
8
|
+
{ci-url}[image:{ci-img}[CI]]
|
9
|
+
{codecov-url}[image:{codecov-img}[codecov]]
|
3
10
|
|
4
11
|
== Installation
|
5
12
|
|
@@ -20,10 +27,6 @@ require "sidekiq"
|
|
20
27
|
require "sidekiq/antidote"
|
21
28
|
|
22
29
|
Sidekiq::Antidote.configure do |config|
|
23
|
-
# Set redis key prefix.
|
24
|
-
# Default: nil
|
25
|
-
config.key_prefix = "my-app:"
|
26
|
-
|
27
30
|
# Set inhibitors cache refresh rate in seconds.
|
28
31
|
# Default: 5.0
|
29
32
|
config.refresh_rate = 10.0
|
@@ -49,36 +52,109 @@ require "sidekiq/web"
|
|
49
52
|
require "sidekiq/antidote/web"
|
50
53
|
----
|
51
54
|
|
55
|
+
=== Middleware(s)
|
52
56
|
|
53
|
-
|
57
|
+
`Sidekiq::Antidote` relies on following bundled middlewares:
|
54
58
|
|
55
|
-
|
59
|
+
* `Sidekiq::Antidote::Middlewares::Client`
|
60
|
+
* `Sidekiq::Antidote::Middlewares::Server`
|
56
61
|
|
57
|
-
|
58
|
-
|
59
|
-
* Ruby 3.2.x
|
62
|
+
The middleware is automatically injected when you require `sidekiq/antidote`.
|
63
|
+
In rare cases, when this causes an issue, you can change middleware order manually:
|
60
64
|
|
61
|
-
|
65
|
+
[source,ruby]
|
66
|
+
----
|
67
|
+
Sidekiq.configure_client do |config|
|
68
|
+
# ...
|
62
69
|
|
63
|
-
|
64
|
-
|
70
|
+
config.client_middleware do |chain|
|
71
|
+
chain.prepend(Sidekiq::Antidote::Middlewares::Client)
|
72
|
+
end
|
73
|
+
end
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
75
|
+
Sidekiq.configure_server do |config|
|
76
|
+
# ...
|
77
|
+
|
78
|
+
config.client_middleware do |chain|
|
79
|
+
chain.prepend(Sidekiq::Antidote::Middlewares::Client)
|
80
|
+
end
|
81
|
+
|
82
|
+
config.server_middleware do |chain|
|
83
|
+
chain.prepend(Sidekiq::Antidote::Middlewares::Server)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
----
|
87
|
+
|
88
|
+
See: https://github.com/sidekiq/sidekiq/blob/main/lib/sidekiq/middleware/chain.rb
|
89
|
+
|
90
|
+
|
91
|
+
== Inhibitors
|
92
|
+
|
93
|
+
=== Treatments
|
73
94
|
|
95
|
+
When adding antidote you must pick on of the treatments:
|
74
96
|
|
75
|
-
|
97
|
+
skip::
|
98
|
+
Skip the job (don't enqueue and/or perform)
|
99
|
+
kill::
|
100
|
+
Kill the job (send to the dead set instead of enqueueing and/or performing)
|
76
101
|
|
77
|
-
This library aims to support and work with following Sidekiq versions:
|
78
102
|
|
79
|
-
|
80
|
-
|
81
|
-
|
103
|
+
=== Class Qualifiers
|
104
|
+
|
105
|
+
Class qualifier is the job class pattern. It may match the job class or the job
|
106
|
+
class and method name (when used with ActionMailer delayed deliveries):
|
107
|
+
|
108
|
+
* `ExampleJob`
|
109
|
+
* `Namespaced::ExampleJob`
|
110
|
+
* `UserMailer#welcome`
|
111
|
+
|
112
|
+
You can also use pattern matching:
|
113
|
+
|
114
|
+
*::
|
115
|
+
Matches any number of alpha-numeric characters and underscores:
|
116
|
+
* `*Job` matches: `ExampleJob`, but not `Namespaced::ExampleJob`, or `UserMailer#welcome`
|
117
|
+
* `UserMailer#*` matches any method of `UserMailer`
|
118
|
+
**::
|
119
|
+
Matches any number of components:
|
120
|
+
* `**` mathes any job or mailer method
|
121
|
+
* `A::**::Job` matches `A::B::Job`, `A::B::C::D::CJob`, etc.
|
122
|
+
* `A**::Job` matches `A::Job`, `Abc::Job`, `A::B::Job`, etc.
|
123
|
+
{}::
|
124
|
+
Matches any of the given literal:
|
125
|
+
* `{A,B,C}Job` matches `AJob`, `BJob`, and `CJob`
|
126
|
+
|
127
|
+
|
128
|
+
== Compatibility
|
129
|
+
|
130
|
+
This library aims to support and is tested against:
|
131
|
+
|
132
|
+
* https://www.ruby-lang.org[Ruby]
|
133
|
+
** MRI 3.0.x
|
134
|
+
** MRI 3.1.x
|
135
|
+
** MRI 3.2.x
|
136
|
+
** MRI 3.3.x
|
137
|
+
* https://github.com/sidekiq/sidekiq[Sidekiq]
|
138
|
+
** 7.2.x
|
139
|
+
** 7.3.x
|
140
|
+
* https://redis.io[Redis]
|
141
|
+
** 6.2.x
|
142
|
+
** 7.0.x
|
143
|
+
** 7.2.x
|
144
|
+
|
145
|
+
If something doesn't work on one of these versions, it's a bug.
|
146
|
+
|
147
|
+
This library may inadvertently work (or seem to work) on other Ruby, Redis, and
|
148
|
+
Sidekiq versions, however support will only be provided for the versions listed
|
149
|
+
above.
|
150
|
+
|
151
|
+
If you would like this library to support another Ruby, Redis, or Sidekiq
|
152
|
+
version, you may volunteer to be a maintainer. Being a maintainer entails making
|
153
|
+
sure all tests run and pass on that implementation. When something breaks on
|
154
|
+
your implementation, you will be responsible for providing patches in a timely
|
155
|
+
fashion. If critical issues for a particular implementation exist at the time of
|
156
|
+
a major release, support for that Ruby, Redis, and/or Sidekiq version may be
|
157
|
+
dropped.
|
82
158
|
|
83
159
|
|
84
160
|
== Development
|
@@ -3,53 +3,16 @@
|
|
3
3
|
module Sidekiq
|
4
4
|
module Antidote
|
5
5
|
class Config
|
6
|
-
REDIS_KEY = "sidekiq-antidote"
|
7
|
-
private_constant :REDIS_KEY
|
8
|
-
|
9
6
|
# Default refresh rate
|
10
7
|
REFRESH_RATE = 5.0
|
11
8
|
|
12
|
-
# @return [String?]
|
13
|
-
attr_reader :key_prefix
|
14
|
-
|
15
9
|
# @return [Float]
|
16
10
|
attr_reader :refresh_rate
|
17
11
|
|
18
|
-
# Fully qualified Redis key
|
19
|
-
#
|
20
|
-
# @example Without key prefix (default)
|
21
|
-
# config.redis_key # => "sidekiq-antidote"
|
22
|
-
#
|
23
|
-
# @example With key prefix
|
24
|
-
# config.key_prefix = "foobar:"
|
25
|
-
# config.redis_key # => "foobar:sidekiq-antidote"
|
26
|
-
#
|
27
|
-
# @see #key_prefix
|
28
|
-
# @return [String]
|
29
|
-
attr_reader :redis_key
|
30
|
-
|
31
12
|
def initialize
|
32
|
-
@key_prefix = nil
|
33
|
-
@redis_key = REDIS_KEY
|
34
13
|
@refresh_rate = REFRESH_RATE
|
35
14
|
end
|
36
15
|
|
37
|
-
# Redis key prefix.
|
38
|
-
#
|
39
|
-
# @example
|
40
|
-
# config.key_prefix = "foobar:"
|
41
|
-
# config.redis_key # => "foobar:sidekiq-antidote"
|
42
|
-
#
|
43
|
-
# @see #redis_key
|
44
|
-
# @param value [String, nil] String that should be prepended to redis key
|
45
|
-
# @return [void]
|
46
|
-
def key_prefix=(value)
|
47
|
-
raise ArgumentError, "expected String, or nil; got #{value.class}" unless value.nil? || value.is_a?(String)
|
48
|
-
|
49
|
-
@redis_key = [value, REDIS_KEY].compact.join.freeze
|
50
|
-
@key_prefix = value&.then(&:-@) # Don't freeze original String value if it was unfrozen
|
51
|
-
end
|
52
|
-
|
53
16
|
# Inhibitors cache refresh rate in seconds.
|
54
17
|
#
|
55
18
|
# @param value [Float] refresh interval in seconds
|
@@ -11,8 +11,8 @@ module Sidekiq
|
|
11
11
|
|
12
12
|
# @see https://github.com/sidekiq/sidekiq/wiki/Middleware
|
13
13
|
# @see https://github.com/sidekiq/sidekiq/wiki/Job-Format
|
14
|
-
def call(_, job_payload,
|
15
|
-
yield unless inhibit(job_payload)
|
14
|
+
def call(_, job_payload, queue_name, _)
|
15
|
+
yield unless inhibit(job_payload, queue_name)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -11,8 +11,8 @@ module Sidekiq
|
|
11
11
|
|
12
12
|
# @see https://github.com/sidekiq/sidekiq/wiki/Middleware
|
13
13
|
# @see https://github.com/sidekiq/sidekiq/wiki/Job-Format
|
14
|
-
def call(_, job_payload,
|
15
|
-
yield unless inhibit(job_payload)
|
14
|
+
def call(_, job_payload, queue_name)
|
15
|
+
yield unless inhibit(job_payload, queue_name)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -10,17 +10,27 @@ module Sidekiq
|
|
10
10
|
|
11
11
|
# @return [true] if message was inhibited
|
12
12
|
# @return [false] otherwise
|
13
|
-
def inhibit(message)
|
13
|
+
def inhibit(message, queue_name)
|
14
14
|
job_record = Sidekiq::JobRecord.new(message)
|
15
15
|
inhibitor = Antidote.remedy_for(job_record)
|
16
16
|
return false unless inhibitor
|
17
17
|
|
18
18
|
Antidote.log(:warn) { "I've got a poison! -- #{job_record.display_class}" }
|
19
19
|
Antidote.log(:warn) { "I've got a remedy! -- #{inhibitor}" }
|
20
|
-
|
20
|
+
|
21
|
+
apply_treatment(inhibitor, job_record, queue_name)
|
21
22
|
|
22
23
|
true
|
23
24
|
end
|
25
|
+
|
26
|
+
def apply_treatment(inhibitor, job_record, queue_name)
|
27
|
+
# Ensure message has queue name
|
28
|
+
message = Sidekiq.dump_json(job_record.item.merge({ "queue" => queue_name }))
|
29
|
+
|
30
|
+
case inhibitor.treatment
|
31
|
+
when "kill" then DeadSet.new.kill(message)
|
32
|
+
end
|
33
|
+
end
|
24
34
|
end
|
25
35
|
end
|
26
36
|
end
|
@@ -4,6 +4,7 @@ require "concurrent"
|
|
4
4
|
|
5
5
|
module Sidekiq
|
6
6
|
module Antidote
|
7
|
+
# @api internal
|
7
8
|
# Eventually consistent list of inhibitors. Used by middlewares to avoid
|
8
9
|
# hitting Redis on every lookup.
|
9
10
|
class Remedy
|
@@ -12,9 +13,8 @@ module Sidekiq
|
|
12
13
|
# @param refresh_rate [Float]
|
13
14
|
# @param repository [Repository]
|
14
15
|
def initialize(refresh_rate, repository:)
|
15
|
-
@
|
16
|
-
|
17
|
-
@inhibitors = repository.to_a.freeze
|
16
|
+
@refresher = Concurrent::TimerTask.new(execution_interval: refresh_rate, run_now: true) do
|
17
|
+
repository.to_a.freeze
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -29,7 +29,7 @@ module Sidekiq
|
|
29
29
|
return to_enum __method__ unless block
|
30
30
|
|
31
31
|
start_refresher unless refresher_running?
|
32
|
-
@
|
32
|
+
@refresher.value&.each(&block)
|
33
33
|
|
34
34
|
self
|
35
35
|
end
|
@@ -8,12 +8,7 @@ module Sidekiq
|
|
8
8
|
class Repository
|
9
9
|
include Enumerable
|
10
10
|
|
11
|
-
|
12
|
-
def initialize(redis_key)
|
13
|
-
@redis_key = -redis_key.to_s
|
14
|
-
|
15
|
-
freeze
|
16
|
-
end
|
11
|
+
REDIS_KEY = "sidekiq-antidote"
|
17
12
|
|
18
13
|
# @overload each
|
19
14
|
# @return [Enumerator<Inhibitor>]
|
@@ -27,7 +22,7 @@ module Sidekiq
|
|
27
22
|
|
28
23
|
broken_ids = []
|
29
24
|
|
30
|
-
redis("HGETALL",
|
25
|
+
redis("HGETALL", REDIS_KEY).each do |id, payload|
|
31
26
|
inhibitor = deserialize(id, payload)
|
32
27
|
next yield inhibitor if inhibitor
|
33
28
|
|
@@ -50,7 +45,7 @@ module Sidekiq
|
|
50
45
|
class_qualifier: class_qualifier
|
51
46
|
)
|
52
47
|
|
53
|
-
return inhibitor if redis("HSETNX",
|
48
|
+
return inhibitor if redis("HSETNX", REDIS_KEY, *serialize(inhibitor)).to_i.positive?
|
54
49
|
end
|
55
50
|
|
56
51
|
raise "can't generate available ID"
|
@@ -59,7 +54,7 @@ module Sidekiq
|
|
59
54
|
# @param ids [Array<String>]
|
60
55
|
# @return [nil]
|
61
56
|
def delete(*ids)
|
62
|
-
redis("HDEL",
|
57
|
+
redis("HDEL", REDIS_KEY, *ids) unless ids.empty?
|
63
58
|
nil
|
64
59
|
end
|
65
60
|
|
data/lib/sidekiq/antidote.rb
CHANGED
@@ -14,9 +14,10 @@ require_relative "./antidote/version"
|
|
14
14
|
module Sidekiq
|
15
15
|
module Antidote
|
16
16
|
MUTEX = Mutex.new
|
17
|
+
private_constant :MUTEX
|
17
18
|
|
18
19
|
@config = Config.new.freeze
|
19
|
-
@repository = Repository.new
|
20
|
+
@repository = Repository.new
|
20
21
|
@remedy = Remedy.new(@config.refresh_rate, repository: @repository)
|
21
22
|
|
22
23
|
class << self
|
@@ -32,10 +33,6 @@ module Sidekiq
|
|
32
33
|
# @return (see Repository#delete)
|
33
34
|
def_delegators :@repository, :delete
|
34
35
|
|
35
|
-
# @!attribute [r] redis_key
|
36
|
-
# @return [String]
|
37
|
-
def_delegators :@config, :redis_key
|
38
|
-
|
39
36
|
# @return [Array<Inhibitor>] Live list of inhibitors
|
40
37
|
def inhibitors
|
41
38
|
@repository.to_a
|
@@ -62,8 +59,7 @@ module Sidekiq
|
|
62
59
|
|
63
60
|
yield config
|
64
61
|
|
65
|
-
@config
|
66
|
-
@repository = Repository.new(@config.redis_key)
|
62
|
+
@config = config.freeze
|
67
63
|
|
68
64
|
self
|
69
65
|
ensure
|
data/web/locales/en.yml
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
---
|
2
2
|
en:
|
3
3
|
antidote.treatment: Treatment
|
4
|
-
antidote.
|
4
|
+
antidote.class_qualifier: Class Qualifier
|
5
5
|
antidote.actions: Actions
|
6
6
|
antidote.add: Add Inhibitor
|
7
|
-
antidote.submit: Submit
|
7
|
+
antidote.add.submit: Submit
|
8
|
+
antidote.add.confirm: Are you sure you want to add the inhibitor?
|
8
9
|
antidote.no_inhibitors: No inhibitors found
|
10
|
+
antidote.delete.confirm: Are you sure you want to delete inhibitor of ‹%{qualifier}› with ‹%{treatment}› treatment?
|
data/web/views/add.html.erb
CHANGED
@@ -6,26 +6,51 @@
|
|
6
6
|
<div class="alert alert-danger"><%= @error %></div>
|
7
7
|
<% end %>
|
8
8
|
|
9
|
-
<
|
10
|
-
<%=
|
11
|
-
|
12
|
-
<div class="form-group
|
13
|
-
<label
|
14
|
-
<
|
15
|
-
|
16
|
-
<
|
9
|
+
<div class="col-sm-12">
|
10
|
+
<form id="antidote-inhibitor" class="form-horizontal" action="<%=root_path %>antidote/add" method="post">
|
11
|
+
<%= csrf_tag %>
|
12
|
+
<div class="form-group">
|
13
|
+
<label class="col-sm-2 control-label"><%= t("antidote.treatment") %></label>
|
14
|
+
<div class="radio col-sm-10">
|
15
|
+
<label>
|
16
|
+
<input id="antidote-inhibitor-treatment-skip" type="radio" name="treatment" value="skip" <%= "checked" if "skip" == @treatment %>>
|
17
|
+
skip <em class="text-muted">(don't enqueue and/or perform)</em>
|
18
|
+
</label>
|
19
|
+
</div>
|
20
|
+
<div class="radio col-sm-offset-2 col-sm-10">
|
21
|
+
<label>
|
22
|
+
<input id="antidote-inhibitor-treatment-kill" type="radio" name="treatment" value="kill" <%= "checked" if "kill" == @treatment %>>
|
23
|
+
kill <em class="text-muted">(send to the dead set instead of enqueueing and/or performing)</em>
|
24
|
+
</label>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
<div class="form-group <%= "has-error" if @class_qualifier_error %>">
|
28
|
+
<label class="col-sm-2 control-label"><%= t("antidote.class_qualifier") %></label>
|
29
|
+
<div class="col-sm-10">
|
30
|
+
<input id="antidote-inhibitor-class-qualifier" type="text" class="form-control <%= "is-invalid" if @class_qualifier_error %>" name="class_qualifier" value="<%= @class_qualifier %>">
|
31
|
+
<% if @class_qualifier_error %>
|
32
|
+
<div id="antidote-inhibitor-class-qualifier-error" class="help-block">
|
33
|
+
<strong>ERROR:</strong> <%= @class_qualifier_error %>
|
34
|
+
</div>
|
17
35
|
<% end %>
|
18
|
-
|
36
|
+
<div class="help-block">
|
37
|
+
<strong>Examples:</strong>
|
38
|
+
<ul class="list-unstyled">
|
39
|
+
<li><kbd>ExampleJob</kbd> to match <var>ExampleJob</var> exactly</li>
|
40
|
+
<li><kbd>Namespaced::ExampleJob</kbd> to match <var>Namespaced::ExampleJob</var> exactly</li>
|
41
|
+
<li><kbd>UserMailer#welcome</kbd> to match <var>welcome</var> method of <var>UserMailer</var></li>
|
42
|
+
<li><kbd>*Job</kbd> to match <var>ExampleJob</var>, but not <var>Namespaced::ExampleJob</var></li>
|
43
|
+
<li><kbd>UserMailer#*</kbd> to match any method of <var>UserMailer</var></li>
|
44
|
+
<li><kbd>**Job</kbd> to match <var>ExampleJob</var>, <var>Namespaced::ExampleJob</var>, etc.</li>
|
45
|
+
<li><kbd>{A,B,C}Job</kbd> to match <var>AJob</var>, <var>BJob</var>, or <var>CJob</var></li>
|
46
|
+
</ul>
|
47
|
+
</div>
|
48
|
+
</div>
|
19
49
|
</div>
|
20
|
-
<div class="form-group
|
21
|
-
<
|
22
|
-
|
23
|
-
|
24
|
-
<div id="antidote-inhibitor-class-qualifier-error" class="invalid-feedback"><%= @class_qualifier_error %></div>
|
25
|
-
<% end %>
|
50
|
+
<div class="form-group">
|
51
|
+
<div class="radio col-sm-offset-2 col-sm-10">
|
52
|
+
<input class="btn btn-danger" type="submit" name="add" value="<%= t("antidote.add.submit") %>" data-confirm="<%= t("antidote.add.confirm") %>" />
|
53
|
+
</div>
|
26
54
|
</div>
|
27
|
-
</
|
28
|
-
|
29
|
-
<button id="antidote-inhibitor-submit" type="submit" class="btn"><%= t("antidote.submit") %></button>
|
30
|
-
</div>
|
31
|
-
</form>
|
55
|
+
</form>
|
56
|
+
</div>
|
data/web/views/index.html.erb
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
<table class="antidote table table-hover table-bordered table-striped">
|
13
13
|
<thead>
|
14
14
|
<th><%= t("antidote.treatment") %></th>
|
15
|
-
<th><%= t("antidote.
|
15
|
+
<th><%= t("antidote.class_qualifier") %></th>
|
16
16
|
<th><%= t("antidote.actions") %></th>
|
17
17
|
</thead>
|
18
18
|
<tbody>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
<td class="delete-confirm">
|
24
24
|
<form action="<%=root_path %>antidote/<%= CGI.escape(inhibitor.id) %>/delete" method="post">
|
25
25
|
<%= csrf_tag %>
|
26
|
-
<input class="btn btn-danger" type="submit" name="delete" value="<%= t("Delete") %>" data-confirm="<%= t("
|
26
|
+
<input class="btn btn-danger" type="submit" name="delete" value="<%= t("Delete") %>" data-confirm="<%= t("antidote.delete.confirm", treatment: inhibitor.treatment, qualifier: inhibitor.class_qualifier) %>" />
|
27
27
|
</form>
|
28
28
|
</td>
|
29
29
|
</tr>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-antidote
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey Zapparov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '7.
|
33
|
+
version: '7.2'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '7.
|
40
|
+
version: '7.2'
|
41
41
|
description:
|
42
42
|
email:
|
43
43
|
- alexey@zapparov.com
|
@@ -66,9 +66,9 @@ licenses:
|
|
66
66
|
- MIT
|
67
67
|
metadata:
|
68
68
|
homepage_uri: https://github.com/ixti/sidekiq-antidote
|
69
|
-
source_code_uri: https://github.com/ixti/sidekiq-antidote/tree/v1.
|
69
|
+
source_code_uri: https://github.com/ixti/sidekiq-antidote/tree/v1.1.0
|
70
70
|
bug_tracker_uri: https://github.com/ixti/sidekiq-antidote/issues
|
71
|
-
changelog_uri: https://github.com/ixti/sidekiq-antidote/blob/v1.
|
71
|
+
changelog_uri: https://github.com/ixti/sidekiq-antidote/blob/v1.1.0/CHANGES.md
|
72
72
|
rubygems_mfa_required: 'true'
|
73
73
|
post_install_message:
|
74
74
|
rdoc_options: []
|
@@ -81,11 +81,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
81
|
version: '3.0'
|
82
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
83
|
requirements:
|
84
|
-
- - "
|
84
|
+
- - ">="
|
85
85
|
- !ruby/object:Gem::Version
|
86
|
-
version:
|
86
|
+
version: '0'
|
87
87
|
requirements: []
|
88
|
-
rubygems_version: 3.
|
88
|
+
rubygems_version: 3.5.22
|
89
89
|
signing_key:
|
90
90
|
specification_version: 4
|
91
91
|
summary: Sidekiq poison-pill instant remedy
|