sidekiq-pauzer 4.2.1 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7ba4ea9d9b061ee7d506874e2f6dd7e3128d912f194df3f7eea66e134ee5342
4
- data.tar.gz: e7c7a9140a6fb5e450b13ab2f97740908036d4cca4d28a1dbb40cea1210ce7b9
3
+ metadata.gz: c5f31ae5cfdfd5dd4e693e42c0bb82fbef4012cf9289772542f32131d996ecf7
4
+ data.tar.gz: 9bf1d72ce135955e7887b0926df8b83e6e3333e2c86f7ba1f7070c1277a4c6fd
5
5
  SHA512:
6
- metadata.gz: 1abbf6aa4603205e520b197f93b08f6ad485a285c33dd64bb1b7eb01b8e54f80f0622a816d2fabf43b369c16abdf73beda3b220446ea023f9fe197bd11eeb7f0
7
- data.tar.gz: f70b7cff1ef0955a932c0df368425213524bcf286d6ec4bc9803cf2486c246b835d2c6ae5c3c1f118b7c7adcc09e929a124295218183e45daf266eebca779535
6
+ metadata.gz: 3c7d00653876ac75e9cf299ad49152d8818380de5c18e670f023dfa5ffa07c9dd2b2755a8cfab71a9cb37e7b7d46d4e119653b314425ef8ffb57c1ffaa87414c
7
+ data.tar.gz: 89ab9cc7e4b0b90b4e3fa1b54b6a8e50577f52738faf0b96030edadc5fdddc1f6fd170b49aaf32be88a3538c31136404ee31576bf258ed2c7896584b189061cc
data/README.adoc CHANGED
@@ -1,5 +1,12 @@
1
1
  = Sidekiq::Pauzer
2
2
 
3
+ :ci-url: https://github.com/ixti/sidekiq-pauzer/actions/workflows/ci.yml?query=branch%3Amain
4
+ :ci-img: https://github.com/ixti/sidekiq-pauzer/actions/workflows/ci.yml/badge.svg?branch=main
5
+ :codecov-url: https://codecov.io/gh/ixti/sidekiq-pauzer/tree/main
6
+ :codecov-img: https://codecov.io/gh/ixti/sidekiq-pauzer/graph/badge.svg?token=UKXUG2AA89
7
+
8
+ {ci-url}[image:{ci-img}[CI]]
9
+ {codecov-url}[image:{codecov-img}[codecov]]
3
10
 
4
11
  == Installation
5
12
 
@@ -20,13 +27,9 @@ require "sidekiq"
20
27
  require "sidekiq/pauzer"
21
28
 
22
29
  Sidekiq::Pauzer.configure do |config|
23
- # Set redis key prefix.
24
- # Default: nil
25
- config.key_prefix = "my-app:"
26
-
27
30
  # Set paused queues local cache refresh rate in seconds.
28
- # Default: 10
29
- config.refresh_rate = 15
31
+ # Default: 5.0
32
+ config.refresh_rate = 10.0
30
33
  end
31
34
  ----
32
35
 
@@ -100,8 +103,6 @@ dropped.
100
103
 
101
104
  This library aims to support and work with following Sidekiq versions:
102
105
 
103
- * Sidekiq 7.0.x
104
- * Sidekiq 7.1.x
105
106
  * Sidekiq 7.2.x
106
107
 
107
108
 
@@ -3,59 +3,25 @@
3
3
  module Sidekiq
4
4
  module Pauzer
5
5
  class Config
6
- REDIS_KEY = "sidekiq-pauzer"
7
- private_constant :REDIS_KEY
8
-
9
6
  # Default refresh rate
10
- REFRESH_RATE = 10
11
-
12
- # @return [String?]
13
- attr_reader :key_prefix
7
+ REFRESH_RATE = 5.0
14
8
 
15
- # @return [Integer, Float]
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-pauzer"
22
- #
23
- # @example With key prefix
24
- # config.key_prefix = "foobar:"
25
- # config.redis_key # => "foobar:sidekiq-pauzer"
26
- #
27
- # @return [String]
28
- attr_reader :redis_key
29
-
30
12
  def initialize
31
- @key_prefix = nil
32
- @redis_key = REDIS_KEY
33
13
  @refresh_rate = REFRESH_RATE
34
14
  end
35
15
 
36
- # Set redis key prefix.
37
- #
38
- # @see redis_key
39
- # @param value [String?] String that should be prepended to redis key
40
- # @return [void]
41
- def key_prefix=(value)
42
- raise ArgumentError, "expected String, or nil; got #{value.class}" unless value.is_a?(String) || value.nil?
43
-
44
- @redis_key = [value, REDIS_KEY].compact.join.freeze
45
- @key_prefix = value&.then(&:-@) # Don't freeze original String value if it was unfrozen
46
- end
47
-
48
16
  # Set paused queues local cache refresh rate in seconds.
49
17
  #
50
- # @param value [Float, Integer] refresh interval in seconds
18
+ # @param value [Float] refresh interval in seconds
51
19
  # @return [void]
52
20
  def refresh_rate=(value)
53
- unless value.is_a?(Integer) || value.is_a?(Float)
54
- raise ArgumentError, "expected Integer, or Float; got #{value.class}"
21
+ unless value.is_a?(Float) && value.positive?
22
+ raise ArgumentError, "expected positive Float; got #{value.inspect}"
55
23
  end
56
24
 
57
- raise ArgumentError, "expected positive value; got #{value.inspect}" unless value.positive?
58
-
59
25
  @refresh_rate = value
60
26
  end
61
27
  end
@@ -6,97 +6,54 @@ require "concurrent"
6
6
  module Sidekiq
7
7
  module Pauzer
8
8
  # @api internal
9
+ # Eventually consistent list of paused queues. Used by Sidekiq fetchers to
10
+ # avoid hitting Redis on every fetch call.
9
11
  class Queues
10
- extend Forwardable
11
12
  include Enumerable
12
13
 
13
- # @!attribute [r] redis_key
14
- # @see (Config#redis_key)
15
- def_delegators :@config, :redis_key
16
-
17
- # @!attribute [r] refresh_rate
18
- # @see (Config#refresh_rate)
19
- def_delegators :@config, :refresh_rate
20
-
21
- # @param config [Config]
22
- def initialize(config)
23
- @config = config
24
- @names = [].freeze
25
- @names_mutex = Mutex.new
26
- @refresher = nil
27
- @refresher_mutex = Mutex.new
14
+ # @param refresh_rate [Float]
15
+ # @param repository [Repository]
16
+ def initialize(refresh_rate, repository:)
17
+ @names = [].freeze
18
+ @refresher = Concurrent::TimerTask.new(execution_interval: refresh_rate, run_now: true) do
19
+ @names = repository.to_a.freeze
20
+ end
28
21
  end
29
22
 
23
+ # @overload each
24
+ # @return [Enumerator<String>]
25
+ #
26
+ # @overload each(&block)
27
+ # For a block { |queue_name| ... }
28
+ # @yieldparam queue_name [String]
29
+ # @return [self]
30
30
  def each(&block)
31
31
  return to_enum __method__ unless block
32
32
 
33
33
  start_refresher unless refresher_running?
34
- @names_mutex.synchronize { @names.dup }.each(&block)
35
-
36
- self
37
- end
34
+ @names.each(&block)
38
35
 
39
- # @param name [#to_s]
40
- # @return [Queues] self
41
- def pause!(name)
42
- redis_call("SADD", redis_key, name.to_s)
43
- refresh
44
36
  self
45
37
  end
46
38
 
47
- # @param name [#to_s]
48
- # @return [Queues] self
49
- def unpause!(name)
50
- redis_call("SREM", redis_key, name.to_s)
51
- refresh
52
- self
53
- end
54
-
55
- # @param name [#to_s]
56
- # @return [Boolean]
57
- def paused?(name)
58
- include?(name.to_s)
59
- end
60
-
39
+ # Starts paused queues list async poller.
40
+ #
41
+ # @return [self]
61
42
  def start_refresher
62
- @refresher_mutex.synchronize do
63
- @refresher&.shutdown
64
- @refresher = Concurrent::TimerTask.execute(execution_interval: refresh_rate, run_now: true) { refresh }
65
- end
66
-
43
+ @refresher.execute
67
44
  self
68
45
  end
69
46
 
47
+ # Stops paused queues list async poller.
48
+ #
49
+ # @return [self]
70
50
  def stop_refresher
71
- @refresher_mutex.synchronize do
72
- @refresher&.shutdown
73
- @refresher = nil
74
- end
75
-
51
+ @refresher.shutdown
76
52
  self
77
53
  end
78
54
 
79
55
  def refresher_running?
80
- @refresher_mutex.synchronize do
81
- @refresher&.running? || false
82
- end
83
- end
84
-
85
- private
86
-
87
- # @return [nil]
88
- def refresh
89
- names = redis_call("SMEMBERS", redis_key).to_a
90
-
91
- @names_mutex.synchronize do
92
- @names = names.each(&:freeze).freeze
93
- end
94
-
95
- nil
96
- end
97
-
98
- def redis_call(...)
99
- Sidekiq.redis { |conn| conn.call(...) }
56
+ @refresher.running?
100
57
  end
101
58
  end
102
59
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ module Pauzer
5
+ class Repository
6
+ include Enumerable
7
+
8
+ REDIS_KEY = "sidekiq-pauzer"
9
+
10
+ # @overload each
11
+ # @return [Enumerator<String>]
12
+ #
13
+ # @overload each(&block)
14
+ # For a block { |queue_name| ... }
15
+ # @yieldparam queue_name [String]
16
+ # @return [self]
17
+ def each
18
+ return to_enum __method__ unless block_given?
19
+
20
+ redis_call("SMEMBERS", REDIS_KEY).each { yield _1.freeze }
21
+
22
+ self
23
+ end
24
+
25
+ # @param queue_name [#to_s]
26
+ # @return [void]
27
+ def add(queue_name)
28
+ redis_call("SADD", REDIS_KEY, queue_name.to_s)
29
+ nil
30
+ end
31
+
32
+ # @param queue_name [#to_s]
33
+ # @return [void]
34
+ def delete(queue_name)
35
+ redis_call("SREM", REDIS_KEY, queue_name.to_s)
36
+ nil
37
+ end
38
+
39
+ # @param name [#to_s]
40
+ # @return [void]
41
+ def include?(queue_name)
42
+ redis_call("SISMEMBER", REDIS_KEY, queue_name.to_s).positive?
43
+ end
44
+
45
+ private
46
+
47
+ def redis_call(...)
48
+ Sidekiq.redis { _1.call(...) }
49
+ end
50
+ end
51
+ end
52
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sidekiq
4
4
  module Pauzer
5
- VERSION = "4.2.1"
5
+ VERSION = "5.1.0"
6
6
  end
7
7
  end
@@ -1,54 +1,51 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "forwardable"
4
3
  require "sidekiq"
5
4
  require "sidekiq/api"
6
5
 
7
- require_relative "./pauzer/config"
8
- require_relative "./pauzer/patches/basic_fetch"
9
- require_relative "./pauzer/patches/queue"
10
- require_relative "./pauzer/queues"
11
- require_relative "./pauzer/version"
12
-
13
6
  begin
7
+ # :nocov:
14
8
  require "sidekiq-ent/version"
9
+ raise "sidekiq-pauzer is incompatible with Sidekiq Enterprise"
10
+ # :nocov:
15
11
  rescue LoadError
16
12
  # All good - no compatibility issues
17
13
  end
18
14
 
19
15
  begin
16
+ # :nocov:
20
17
  require "sidekiq/pro/version"
18
+ raise "sidekiq-pauzer is incompatible with Sidekiq Pro"
19
+ # :nocov:
21
20
  rescue LoadError
22
21
  # All good - no compatibility issues
23
22
  end
24
23
 
25
- raise "sidekiq-pauzer is incompatible with Sidekiq Pro" if Sidekiq.pro?
26
- raise "sidekiq-pauzer is incompatible with Sidekiq Enterprise" if Sidekiq.ent?
24
+ require_relative "./pauzer/config"
25
+ require_relative "./pauzer/patches/basic_fetch"
26
+ require_relative "./pauzer/patches/queue"
27
+ require_relative "./pauzer/queues"
28
+ require_relative "./pauzer/repository"
29
+ require_relative "./pauzer/version"
27
30
 
28
31
  module Sidekiq
29
32
  module Pauzer
30
33
  MUTEX = Mutex.new
34
+ private_constant :MUTEX
31
35
 
32
- @config = Config.new.freeze
33
- @queues = Queues.new(@config)
36
+ @config = Config.new.freeze
37
+ @repository = Repository.new
38
+ @queues = Queues.new(@config.refresh_rate, repository: @repository)
34
39
 
35
40
  class << self
36
- extend Forwardable
37
-
38
- # @!attribute [r] redis_key
39
- # @see Config#redis_key
40
- # @return [String]
41
- def_delegators :@config, :redis_key
42
-
43
41
  # @example
44
42
  # Sidekiq::Pauzer.pause!("minor")
45
43
  # Sidekiq::Pauzer.paused?("minor") # => true
46
44
  #
47
- # @param (see Queues#pause!)
45
+ # @param (see Repository#add)
48
46
  # @return [void]
49
- def pause!(name)
50
- @queues.pause!(name)
51
-
47
+ def pause!(queue_name)
48
+ @repository.add(queue_name)
52
49
  nil
53
50
  end
54
51
 
@@ -58,11 +55,10 @@ module Sidekiq
58
55
  # Sidekiq::Pauzer.unpause!("minor")
59
56
  # Sidekiq::Pauzer.paused?("minor") # => false
60
57
  #
61
- # @param (see Queues#unpause!)
58
+ # @param (see Repository#delete)
62
59
  # @return [void]
63
- def unpause!(name)
64
- @queues.unpause!(name)
65
-
60
+ def unpause!(queue_name)
61
+ @repository.delete(queue_name)
66
62
  nil
67
63
  end
68
64
 
@@ -71,11 +67,13 @@ module Sidekiq
71
67
  # Sidekiq::Pauzer.paused?("minor") # => true
72
68
  # Sidekiq::Pauzer.paused?("threat") # => false
73
69
  #
74
- # @see Queues#paused?
75
- def paused?(name)
76
- @queues.paused?(name)
70
+ # @return (see Repository#include?)
71
+ def paused?(queue_name)
72
+ @repository.include?(queue_name)
77
73
  end
78
74
 
75
+ # Eventually consistent list of paused queues.
76
+ #
79
77
  # @example
80
78
  # Sidekiq::Pauzer.pause!("minor")
81
79
  # Sidekiq::Pauzer.paused_queues # => ["minor"]
@@ -123,7 +121,7 @@ module Sidekiq
123
121
 
124
122
  def reinit_queues
125
123
  @queues.stop_refresher
126
- @queues = Queues.new(@config)
124
+ @queues = Queues.new(@config.refresh_rate, repository: @repository)
127
125
  end
128
126
  end
129
127
  end
data/web/views/queues.erb CHANGED
@@ -20,8 +20,12 @@
20
20
  <span class="label label-danger"><%= t('Paused') %></span>
21
21
  <% end %>
22
22
  </td>
23
- <td><%= number_with_delimiter(queue.size) %> </td>
24
- <td><% queue_latency = queue.latency %><%= number_with_delimiter(queue_latency.round(2)) %><%= (queue_latency < 60) ? '' : " (#{relative_time(Time.at(Time.now.to_f - queue_latency))})" %> </td>
23
+ <td class="num"><%= number_with_delimiter(queue.size) %> </td>
24
+ <td class="num">
25
+ <% queue_latency = queue.latency %>
26
+ <%= (queue_latency < 60) ? '' : " (#{relative_time(Time.at(Time.now.to_f - queue_latency))})" %>
27
+ <%= number_with_delimiter(queue_latency, precision: 2) %>
28
+ </td>
25
29
  <td class="delete-confirm">
26
30
  <form action="<%=root_path %>queues/<%= CGI.escape(queue.name) %>" method="post">
27
31
  <%= csrf_tag %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-pauzer
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.1
4
+ version: 5.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: 2023-11-26 00:00:00.000000000 Z
11
+ date: 2023-12-10 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.0'
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.0'
40
+ version: '7.2'
41
41
  description:
42
42
  email:
43
43
  - alexey@zapparov.com
@@ -55,6 +55,7 @@ files:
55
55
  - lib/sidekiq/pauzer/patches/web_action.rb
56
56
  - lib/sidekiq/pauzer/patches/web_application.rb
57
57
  - lib/sidekiq/pauzer/queues.rb
58
+ - lib/sidekiq/pauzer/repository.rb
58
59
  - lib/sidekiq/pauzer/version.rb
59
60
  - lib/sidekiq/pauzer/web.rb
60
61
  - web/views/queues.erb
@@ -63,9 +64,9 @@ licenses:
63
64
  - MIT
64
65
  metadata:
65
66
  homepage_uri: https://github.com/ixti/sidekiq-pauzer
66
- source_code_uri: https://github.com/ixti/sidekiq-pauzer/tree/v4.2.1
67
+ source_code_uri: https://github.com/ixti/sidekiq-pauzer/tree/v5.1.0
67
68
  bug_tracker_uri: https://github.com/ixti/sidekiq-pauzer/issues
68
- changelog_uri: https://github.com/ixti/sidekiq-pauzer/blob/v4.2.1/CHANGES.md
69
+ changelog_uri: https://github.com/ixti/sidekiq-pauzer/blob/v5.1.0/CHANGES.md
69
70
  rubygems_mfa_required: 'true'
70
71
  post_install_message:
71
72
  rdoc_options: []