sidekiq-debouncer 3.1.0 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a48a55ff72c620ec5c777c51d93008502eee9a5a5e6ac5678936a0a937f9300
4
- data.tar.gz: a3a99b8171604c90d3e3fb2ee2665e8601d2a53e22cae488d7a3018f298c734a
3
+ metadata.gz: e4a9a96453d838cc36e81e1fe2d68ac8269a86b17d6db437f84aec0b599267cf
4
+ data.tar.gz: bbd138d4b850c86ecdac14e2d9857444c92ec9811a3612e19627aee3145873e1
5
5
  SHA512:
6
- metadata.gz: caf0fe8240dd387090d730f7421ed6f92897bbbb770410b7f2861f1bf898f261c8cf801519c9f974c50e9a4929fff3da5f275280bca4de4506bf17ea48fbaff4
7
- data.tar.gz: 262ca59401d304f301413beda565c40f2557a2352f156ad84e9422e0ab2cf30006e7038e31bcbb67c80ecbe4a575880a3074e6ec74657c74fca4ce250f645c61
6
+ metadata.gz: 7d7457e8273f79dac578f78231d5ce73380259076bae636a362124b54c26acd2d4ebc487598dfad7dcb529a023e246beabcf7d24383159f0abde667caec822bc
7
+ data.tar.gz: 9d730f2c1f36671a550a80a222a1f363f79624b2f0f74ceefc70d7928c06a40ef556a7cb3e360088ee482755d99c610323a9699f3db5b4dfee5de284bd1d9600
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [3.2.0] - 2026-02-15
2
+ - Support extra attributes ([#37](https://github.com/paladinsoftware/sidekiq-debouncer/pull/37))
3
+ - Fix loading order issues ([#36](https://github.com/paladinsoftware/sidekiq-debouncer/pull/36))
4
+ - Bump Ruby and Sidekiq versions ([#35](https://github.com/paladinsoftware/sidekiq-debouncer/pull/35))
5
+
1
6
  ## [3.1.0] - 2025-03-28
2
7
  - Drop support for Ruby < 3.2.0
3
8
  - Support for Sidekiq 8 ([#31](https://github.com/paladinsoftware/sidekiq-debouncer/pull/31), [#32](https://github.com/paladinsoftware/sidekiq-debouncer/pull/32))
data/README.md CHANGED
@@ -99,6 +99,12 @@ Sidekiq.configure_client do |config|
99
99
  end
100
100
  ```
101
101
 
102
+ ## Middleware context
103
+
104
+ When multiple jobs are debounced together, the full job hash from the **last job** is preserved. This means any context added by other middlewares (like `acts_as_tenant`, Sidekiq's `CurrentAttributes`, or custom middleware data) will be taken from the most recent job.
105
+
106
+ For example, if you debounce 3 jobs with different tenant contexts, the final executed job will use the tenant from the 3rd (last) job.
107
+
102
108
  ## Web UI
103
109
  Add `require 'sidekiq/debouncer/web'` after `require 'sidekiq/web'`.
104
110
 
@@ -18,11 +18,7 @@ module Sidekiq
18
18
  while !@done && (job, score = zpopbyscore_withscore(conn, [Sidekiq::Debouncer::SET], [Time.now.to_f.to_s]))
19
19
  job_args = zpopbyscore_multi(conn, [job], [score])
20
20
 
21
- final_args = job_args.map { |elem| Sidekiq.load_json(elem.split("-", 2)[1]) }
22
- job_class = job.split("/")[2]
23
- klass = Object.const_get(job_class)
24
-
25
- @client.push({"args" => final_args, "class" => klass, "debounce_key" => job})
21
+ @client.push(JobBuilder.build(job_args, job))
26
22
 
27
23
  logger.debug { "enqueued #{Sidekiq::Debouncer::SET}: #{job}" }
28
24
  end
@@ -3,8 +3,6 @@
3
3
  module Sidekiq
4
4
  module Debouncer
5
5
  class Job
6
- include Sidekiq::JobUtil
7
-
8
6
  attr_reader :key, :score
9
7
 
10
8
  def initialize(key, score)
@@ -17,12 +15,11 @@ module Sidekiq
17
15
  end
18
16
 
19
17
  def args
20
- @_args ||= Sidekiq.redis { |conn| conn.call("ZRANGE", key, "-inf", "+inf", "BYSCORE") }
21
- .map { |elem| Sidekiq.load_json(elem.split("-", 2)[1]) }
18
+ item["args"]
22
19
  end
23
20
 
24
21
  def queue
25
- normalized["queue"]
22
+ item["queue"]
26
23
  end
27
24
 
28
25
  def klass
@@ -31,10 +28,11 @@ module Sidekiq
31
28
 
32
29
  alias_method :display_class, :klass
33
30
 
34
- private
35
-
36
- def normalized
37
- @_normalized ||= normalize_item({"args" => args, "class" => Object.const_get(klass), "debounce_key" => key})
31
+ def item
32
+ @_item ||= begin
33
+ job_args = Sidekiq.redis { |conn| conn.call("ZRANGE", key, "-inf", "+inf", "BYSCORE") }
34
+ JobBuilder.build(job_args, key)
35
+ end
38
36
  end
39
37
  end
40
38
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ module Debouncer
5
+ module JobBuilder
6
+ extend Sidekiq::JobUtil
7
+
8
+ def self.build(job_args, debounce_key)
9
+ base_job = nil
10
+ final_args = job_args.map do |elem|
11
+ if elem.start_with?("{")
12
+ base_job = Sidekiq.load_json(elem)
13
+ base_job["args"]
14
+ else
15
+ Sidekiq.load_json(elem.split("-", 2)[1])
16
+ end
17
+ end
18
+
19
+ if base_job
20
+ base_job.merge("args" => final_args, "debounce_key" => debounce_key)
21
+ else
22
+ # Old format fallback - normalize to get queue from class
23
+ job_class = debounce_key.split("/")[2]
24
+ normalize_item("args" => final_args, "class" => Object.const_get(job_class), "debounce_key" => debounce_key)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "securerandom"
4
-
5
3
  module Sidekiq
6
4
  module Debouncer
7
5
  module Middleware
@@ -42,10 +40,10 @@ module Sidekiq
42
40
 
43
41
  return job.merge("args" => [job["args"]], "debounce_key" => key) if testing?
44
42
 
45
- args_stringified = "#{SecureRandom.hex(12)}-#{Sidekiq.dump_json(job["args"])}"
43
+ job_stringified = Sidekiq.dump_json(job)
46
44
 
47
45
  redis do |connection|
48
- redis_debounce(connection, [Sidekiq::Debouncer::SET, key], [args_stringified, time, @debounce_key_ttl])
46
+ redis_debounce(connection, [Sidekiq::Debouncer::SET, key], [job_stringified, time, @debounce_key_ttl])
49
47
  end
50
48
 
51
49
  # prevent normal sidekiq flow
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sidekiq
4
4
  module Debouncer
5
- VERSION = "3.1.0"
5
+ VERSION = "3.2.0"
6
6
  end
7
7
  end
@@ -34,6 +34,14 @@
34
34
  </code>
35
35
  </td>
36
36
  </tr>
37
+ <% unless retry_extra_items(@job).empty? %>
38
+ <tr>
39
+ <th><%= t('Extras') %></th>
40
+ <td>
41
+ <code><%= retry_extra_items(@job).inspect %></code>
42
+ </td>
43
+ </tr>
44
+ <% end %>
37
45
  </tbody>
38
46
  </table>
39
47
  </div>
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "base64"
4
+ require "sidekiq/api"
5
+ require "sidekiq/debouncer/set"
4
6
 
5
7
  module Sidekiq
6
8
  module Debouncer
@@ -3,10 +3,10 @@
3
3
  require "sidekiq/debouncer/version"
4
4
  require "sidekiq/debouncer/errors"
5
5
  require "sidekiq/debouncer/lua_commands"
6
+ require "sidekiq/debouncer/job_builder"
6
7
  require "sidekiq/debouncer/middleware/client"
7
8
  require "sidekiq/debouncer/middleware/server"
8
9
  require "sidekiq/debouncer/job"
9
- require "sidekiq/debouncer/set"
10
10
 
11
11
  module Sidekiq
12
12
  module Debouncer
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-debouncer
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Zuchmański
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-03-28 00:00:00.000000000 Z
12
+ date: 2026-02-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sidekiq
@@ -148,6 +148,7 @@ files:
148
148
  - lib/sidekiq/debouncer/enq.rb
149
149
  - lib/sidekiq/debouncer/errors.rb
150
150
  - lib/sidekiq/debouncer/job.rb
151
+ - lib/sidekiq/debouncer/job_builder.rb
151
152
  - lib/sidekiq/debouncer/launcher.rb
152
153
  - lib/sidekiq/debouncer/locales/en.yml
153
154
  - lib/sidekiq/debouncer/lua/debounce.lua