sidekiq-bus 0.8.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2c633c91c5b55a5e08ec80f73ee6a174df07d59c
4
- data.tar.gz: '00095d6bcdc1407137cab9051990b91f359df304'
2
+ SHA256:
3
+ metadata.gz: 866c59dd8c86269bcbf074c6f3ee4e4e4ec0e9de7f80535325a8716265166323
4
+ data.tar.gz: 77943838139481632a6647f133fa37e6970a7b4b1cbade052dbf480b46f4dea4
5
5
  SHA512:
6
- metadata.gz: a4dcb3d6a379ceda40fe1da42c6cdb00662b85f37bbfcf9010ed7303883d8e44a9f43f9ab9c587793503ce4ade15a09f1c23cbdd6ec07ae5f4d85af0ce8ced04
7
- data.tar.gz: 2631baff2bc6724686516f34cc04955fef78884228566f961b2f51dd069130bf67c65a562200299e833b241d8ed18c6e7a17636768bfd6310d318de1c8997c0f
6
+ metadata.gz: fecd3c6a09178d511def70fae49a6ca050288f40c02491a656a12f3f4b646fb4ff0386c7eb92d806675a1d734db3ec6c92b71f0718eae4f9b4077db2d002cc5a
7
+ data.tar.gz: 2632c35bc3e5c09b31d03b632796355dc16005e55bcd875956c4c0ed4b1083540c2744d4308fd8a18a880620cba744a352d7c1a698530f70157dad064422d8bf
data/CHANGELOG.md CHANGED
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.0.0] - 2025-05-13
10
+
11
+ ### Changed
12
+ - [BREAKING] Updated sidekiq-scheduler to 4.0.3. This adds support for Redis 5 and Sidekiq 6, but removes support for Redis < 4.2 and Sidekiq < 4.X. The dropped versions are long out of support; please use this release to facilitate an update.
13
+
14
+ ## [0.9.0] - 2019-12-03
15
+
16
+ ### Added
17
+ - Tab in sidekiq web ui for bus info
18
+
9
19
  ### [0.8.2] - 2019-08-06
10
20
 
11
21
  ### Fixed
data/lib/sidekiq-bus.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'queue-bus'
4
4
  require 'sidekiq_bus/adapter'
5
5
  require 'sidekiq_bus/version'
6
+ require 'sidekiq_bus/server'
6
7
  require 'sidekiq_bus/middleware/retry'
7
8
 
8
9
  module SidekiqBus
@@ -0,0 +1,202 @@
1
+
2
+ <script LANGUAGE="JavaScript">
3
+ <!--
4
+ function confirmSubmit()
5
+ {
6
+ var agree=confirm("Are you sure you wish to continue?");
7
+ if (agree)
8
+ return true ;
9
+ else
10
+ return false ;
11
+ }
12
+
13
+ function setSample() {
14
+ var text = document.getElementById("query_attributes").textContent;
15
+ var textArea = document.getElementById('querytext');
16
+ textArea.value = text;
17
+ return false;
18
+ }
19
+ // -->
20
+ </script>
21
+
22
+ <%
23
+ app_hash = {}
24
+ class_hash = {}
25
+ event_hash = {}
26
+ query_string = params[:query].to_s.strip
27
+
28
+ query_attributes = nil
29
+ query_error = nil
30
+ if query_string.length > 0
31
+ begin
32
+ query_attributes = ::SidekiqBus::Server::Helpers.parse_query(query_string)
33
+ raise "Not a JSON Object" unless query_attributes.is_a?(Hash)
34
+ rescue Exception => e
35
+ query_attributes = nil
36
+ query_error = e.message
37
+ end
38
+
39
+ if query_attributes
40
+ # sort keys for display
41
+ query_attributes = ::SidekiqBus::Server::Helpers.sort_query(query_attributes)
42
+ end
43
+ end
44
+
45
+ # collect each differently
46
+ ::QueueBus::Application.all.each do |app|
47
+ app_key = app.app_key
48
+
49
+ subscriptions = ::SidekiqBus::Server::Helpers.query_subscriptions(app, query_attributes)
50
+ subscriptions.each do |sub|
51
+ class_name = sub.class_name
52
+ queue = sub.queue_name
53
+ filters = sub.matcher.filters
54
+ sub_key = sub.key
55
+
56
+ if filters["bus_event_type"]
57
+ event = filters["bus_event_type"]
58
+ else
59
+ event = "see filter"
60
+ end
61
+
62
+ app_hash[app_key] ||= []
63
+ app_hash[app_key] << [sub_key, event, class_name, queue, filters]
64
+
65
+ class_hash[class_name] ||= []
66
+ class_hash[class_name] << [app_key, sub_key, event, queue, filters]
67
+
68
+ event_hash[event] ||= []
69
+ event_hash[event] << [app_key, sub_key, class_name, queue, filters]
70
+ end
71
+ end
72
+
73
+ # sort each list item by secondary label
74
+ class_hash.each do |_, array|
75
+ array.sort!{ |a,b| a.first <=> b.first }
76
+ end
77
+ event_hash.each do |_, array|
78
+ array.sort!{ |a,b| a.first <=> b.first }
79
+ end
80
+
81
+ # helper to display either
82
+ def display_row(name, val, button=nil, first=false)
83
+ form = ""
84
+ if button
85
+ text, url = button
86
+ form = "<form method='POST' action='#{url}' style='float:left; padding:0 5px 0 0;margin:0;'>#{csrf_tag}<input type='submit' name='' value='#{h(text)}' style='padding:0;margin:0;' onclick=\"return confirmSubmit();\"/><input type='hidden' name='name' value='#{h(name)}' /></form>"
87
+ end
88
+
89
+ if !val
90
+ out = "<td>&nbsp;</td><td>&nbsp;</td>"
91
+ else
92
+ one, two, three, queue, filters = val
93
+ out = "<td>#{h(one)}</td><td>#{h(two)}</td><td>#{h(three)}</td><td><a href='#{"queues/#{queue}"}'>#{h(queue)}</a></td>"
94
+ out << "<td>#{h(::QueueBus::Util.encode(filters).gsub(/\"bus_special_value_(\w+)\"/){ "(#{$1})" }).gsub(" ", "&nbsp;").gsub('&quot;,&quot;', '&quot;, &quot;')}</td>"
95
+ end
96
+
97
+ if first
98
+ "<tr><td>#{h(name)}#{form}</td>#{out}</tr>\n"
99
+ else
100
+ "<tr><td>&nbsp;</td>#{out}</tr>\n"
101
+ end
102
+ end
103
+
104
+ def output_hash(hash, action=nil)
105
+ out = ""
106
+ hash.keys.sort.each do |item|
107
+ display = hash[item]
108
+ first = display.shift
109
+ out << display_row(item, first, action, true)
110
+ display.each do |val|
111
+ out << display_row(item, val, action)
112
+ end
113
+ end
114
+ out
115
+ end
116
+ %>
117
+
118
+ <h1 class='wi'>Sample Event</h1>
119
+ <p class='intro'>Enter JSON of an event to see applicable subscriptions.</p>
120
+ <div style="text-align: center;width:700px;">
121
+ -<form method="GET" action="<%= "bus" %>" style="float:none;padding:0;margin:0;">
122
+ <textarea id="querytext" name="query" style="padding: 10px;height:150px;width:700px;font-size:14px;font-family:monospace"><%=
123
+ h(query_string)
124
+ %></textarea>
125
+ <br/>
126
+ <button onclick="window.location.href = '<%= "bus" %>'; return false;">Clear</button>
127
+ <input type="submit" name="" value="Filter results to this event"/>
128
+ </form>
129
+ </div>
130
+
131
+ <% if query_error %>
132
+ <blockquote><pre style="text-align:left;font-family:monospace;margin:5px 0 5px 0;padding:10px;background:#f2dede;color:#a94442;"><code><%=
133
+ h(query_error.strip)
134
+ %></code></pre></blockquote>
135
+ <% end %>
136
+ <% if query_attributes %>
137
+ <blockquote><pre style="text-align:left;font-family:monospace;margin:5px 0 5px 0;padding:10px;background:#dff0d8;color:#3c763d;"><code id="query_attributes"><%=
138
+ h(JSON.pretty_generate(query_attributes).strip)
139
+ %></code></pre></blockquote>
140
+ <div style="text-align:right;">
141
+ <button onclick="return setSample();">Set Sample</button>
142
+ </div>
143
+ <% end %>
144
+
145
+ <hr/>
146
+
147
+ <h1 class='wi'>Applications</h1>
148
+ <p class='intro'>The apps below have registered the given classes and queues.</p>
149
+ <table class='table-striped table-bordered'>
150
+ <thead class="thead-dark">
151
+ <tr>
152
+ <th>App Key</th>
153
+ <th>Subscription Key</th>
154
+ <th>Event Type</th>
155
+ <th>Class Name</th>
156
+ <th>Queue</th>
157
+ <th>Filters</th>
158
+ </tr>
159
+ </thead>
160
+
161
+ <%= output_hash(app_hash, query_attributes ? false : ["Unsubscribe", "bus/unsubscribe"]) %>
162
+ </table>
163
+
164
+ <p>&nbsp;</p>
165
+
166
+ <h1 class='wi'>Events</h1>
167
+ <p class='intro'>The events below have been registered by the given applications and queues.</p>
168
+
169
+ <table class='table-striped table-bordered'>
170
+ <thead class="thead-dark">
171
+ <tr>
172
+ <th>Event Type</th>
173
+ <th>App Key</th>
174
+ <th>Subscription Key</th>
175
+ <th>Class Name</th>
176
+ <th>Queue</th>
177
+ <th>Filters</th>
178
+ </tr>
179
+ </thead>
180
+ <%= output_hash(event_hash, false) %>
181
+ </table>
182
+
183
+
184
+
185
+ <p>&nbsp;</p>
186
+
187
+ <h1 class='wi'>Classes</h1>
188
+ <p class='intro'>The classes below have been registered by the given applications and queues.</p>
189
+ <table class='table-striped table-bordered'>
190
+ <thead class="thead-dark">
191
+ <tr>
192
+ <th>Class Name</th>
193
+ <th>App Key</th>
194
+ <th>Subscription Key</th>
195
+ <th>Event Type</th>
196
+ <th>Queue</th>
197
+ <th>Filters</th>
198
+ </tr>
199
+ </thead>
200
+ <%= output_hash(class_hash, false) %>
201
+ </table>
202
+
@@ -0,0 +1,139 @@
1
+ require 'sidekiq/web'
2
+
3
+ module SidekiqBus
4
+ module Server
5
+ def self.registered(app)
6
+ app.get('/bus') do
7
+ # you can define @instance_variables for passing into template
8
+ # Sidekiq uses erb for its templates so you should do it aswell
9
+ erb File.read(File.join(File.dirname(__FILE__), "server/views/bus.erb"))
10
+ end
11
+
12
+ app.post '/bus/unsubscribe' do
13
+ bus_app = ::QueueBus::Application.new(params[:name]).unsubscribe
14
+ redirect "#{root_path}bus"
15
+ end
16
+ end
17
+
18
+ class Helpers
19
+ class << self
20
+ def parse_query(query_string)
21
+ has_open_brace = query_string.include?("{")
22
+ has_close_brace = query_string.include?("}")
23
+ has_multiple_lines = query_string.include?("\n")
24
+ has_colon = query_string.include?(":")
25
+ has_comma = query_string.include?(",")
26
+ has_quote = query_string.include?("\"")
27
+
28
+ exception = nil
29
+
30
+ # first let's see if it parses
31
+ begin
32
+ query_attributes = JSON.parse(query_string)
33
+ raise "Not a JSON Object" unless query_attributes.is_a?(Hash)
34
+ rescue Exception => e
35
+ exception = e
36
+ end
37
+ return query_attributes unless exception
38
+
39
+ if query_attributes
40
+ # it parsed but it's something else
41
+ if query_attributes.is_a?(Array) && query_attributes.length == 1
42
+ # maybe it's the thing from the queue
43
+ json_string = query_attributes.first
44
+ fixed = JSON.parse(json_string) rescue nil
45
+ return fixed if fixed
46
+ end
47
+
48
+ # something else?
49
+ raise exception
50
+ end
51
+
52
+ if !has_open_brace && !has_close_brace
53
+ # maybe they just forgot the braces
54
+ fixed = JSON.parse("{ #{query_string} }") rescue nil
55
+ return fixed if fixed
56
+ end
57
+
58
+ if !has_open_brace
59
+ # maybe they just forgot the braces
60
+ fixed = JSON.parse("{ #{query_string}") rescue nil
61
+ return fixed if fixed
62
+ end
63
+
64
+ if !has_close_brace
65
+ # maybe they just forgot the braces
66
+ fixed = JSON.parse("#{query_string} }") rescue nil
67
+ return fixed if fixed
68
+ end
69
+
70
+ if !has_multiple_lines && !has_colon && !has_open_brace && !has_close_brace
71
+ # we say they just put a bus_event type here, so help them out
72
+ return {"bus_event_type" => query_string, "more_here" => true}
73
+ end
74
+
75
+ if has_colon && !has_quote
76
+ # maybe it's some search syntax like this: field: value other: true, etc
77
+ # maybe use something like this later: https://github.com/dxwcyber/search-query-parser
78
+
79
+ # quote all the strings, (simply) tries to avoid integers
80
+ test_query = query_string.gsub(/([a-zA-z]\w*)/,'"\0"')
81
+ if !has_comma
82
+ test_query.gsub!("\n", ",\n")
83
+ end
84
+ if !has_open_brace && !has_close_brace
85
+ test_query = "{ #{test_query} }"
86
+ end
87
+
88
+ fixed = JSON.parse(test_query) rescue nil
89
+ return fixed if fixed
90
+ end
91
+
92
+ if has_open_brace && has_close_brace
93
+ # maybe the whole thing is a hash output from a hash.inspect log
94
+ ruby_hash_text = query_string.clone
95
+ # https://stackoverflow.com/questions/1667630/how-do-i-convert-a-string-object-into-a-hash-object
96
+ # Transform object string symbols to quoted strings
97
+ ruby_hash_text.gsub!(/([{,]\s*):([^>\s]+)\s*=>/, '\1"\2"=>')
98
+ # Transform object string numbers to quoted strings
99
+ ruby_hash_text.gsub!(/([{,]\s*)([0-9]+\.?[0-9]*)\s*=>/, '\1"\2"=>')
100
+ # Transform object value symbols to quotes strings
101
+ ruby_hash_text.gsub!(/([{,]\s*)(".+?"|[0-9]+\.?[0-9]*)\s*=>\s*:([^,}\s]+\s*)/, '\1\2=>"\3"')
102
+ # Transform array value symbols to quotes strings
103
+ ruby_hash_text.gsub!(/([\[,]\s*):([^,\]\s]+)/, '\1"\2"')
104
+ # fix up nil situation
105
+ ruby_hash_text.gsub!(/=>nil/, '=>null')
106
+ # Transform object string object value delimiter to colon delimiter
107
+ ruby_hash_text.gsub!(/([{,]\s*)(".+?"|[0-9]+\.?[0-9]*)\s*=>/, '\1\2:')
108
+ fixed = JSON.parse(ruby_hash_text) rescue nil
109
+ return fixed if fixed
110
+ end
111
+
112
+ raise exception
113
+ end
114
+
115
+ def sort_query(query_attributes)
116
+ query_attributes.each do |key, value|
117
+ if value.is_a?(Hash)
118
+ query_attributes[key] = sort_query(value)
119
+ end
120
+ end
121
+ query_attributes.sort_by { |key| key }.to_h
122
+ end
123
+
124
+ def query_subscriptions(app, query_attributes)
125
+ # TODO: all of this can move to method in queue-bus to replace event_display_tuples
126
+ if query_attributes
127
+ subscriptions = app.subscription_matches(query_attributes)
128
+ else
129
+ subscriptions = app.send(:subscriptions).all
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ Sidekiq::Web.register SidekiqBus::Server
138
+ Sidekiq::Web.locales << File.expand_path(File.dirname(__FILE__) + "/web/locales")
139
+ Sidekiq::Web.tabs['Bus'] = 'bus'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SidekiqBus
4
- VERSION = '0.8.2'
4
+ VERSION = '1.0.0'
5
5
  end
data/sidekiq-bus.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.add_dependency('queue-bus', ['>= 0.7', '< 1'])
20
20
  s.add_dependency('sidekiq', ['>= 3.0.0', '~> 5.0'])
21
- s.add_dependency('sidekiq-scheduler', '~> 3.0')
21
+ s.add_dependency('sidekiq-scheduler', ['>= 3.0', '< 5.0'])
22
22
 
23
23
  s.add_development_dependency("rspec")
24
24
  s.add_development_dependency("fakeredis")
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
- require 'celluloid' if Sidekiq::VERSION < '4'
5
4
  require 'sidekiq/scheduled'
6
5
 
7
6
  describe 'Sidekiq Integration' do
@@ -88,22 +87,14 @@ describe 'Sidekiq Integration' do
88
87
  val = QueueBus.redis { |redis| redis.lpop('queue:bus_incoming') }
89
88
  expect(val).to eq(nil) # nothing really added
90
89
 
91
- if Sidekiq::VERSION < '4'
92
- Sidekiq::Scheduled::Poller.new.poll
93
- else
94
- Sidekiq::Scheduled::Poller.new.enqueue
95
- end
90
+ Sidekiq::Scheduled::Poller.new.enqueue
96
91
 
97
92
  val = QueueBus.redis { |redis| redis.lpop('queue:bus_incoming') }
98
93
  expect(val).to eq(nil) # nothing added yet
99
94
 
100
95
  # process scheduler in future
101
96
  Timecop.freeze(worktime) do
102
- if Sidekiq::VERSION < '4'
103
- Sidekiq::Scheduled::Poller.new.poll
104
- else
105
- Sidekiq::Scheduled::Poller.new.enqueue
106
- end
97
+ Sidekiq::Scheduled::Poller.new.enqueue
107
98
 
108
99
  val = QueueBus.redis { |redis| redis.lpop('queue:bus_incoming') }
109
100
  hash = JSON.parse(val)
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-bus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Leonard
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-08-06 00:00:00.000000000 Z
10
+ date: 2025-05-13 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: queue-bus
@@ -54,16 +53,22 @@ dependencies:
54
53
  name: sidekiq-scheduler
55
54
  requirement: !ruby/object:Gem::Requirement
56
55
  requirements:
57
- - - "~>"
56
+ - - ">="
58
57
  - !ruby/object:Gem::Version
59
58
  version: '3.0'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
60
62
  type: :runtime
61
63
  prerelease: false
62
64
  version_requirements: !ruby/object:Gem::Requirement
63
65
  requirements:
64
- - - "~>"
66
+ - - ">="
65
67
  - !ruby/object:Gem::Version
66
68
  version: '3.0'
69
+ - - "<"
70
+ - !ruby/object:Gem::Version
71
+ version: '5.0'
67
72
  - !ruby/object:Gem::Dependency
68
73
  name: rspec
69
74
  requirement: !ruby/object:Gem::Requirement
@@ -171,11 +176,8 @@ extensions: []
171
176
  extra_rdoc_files: []
172
177
  files:
173
178
  - ".gitignore"
174
- - ".rbenv-version"
175
179
  - ".rspec"
176
180
  - ".rubocop.yml"
177
- - ".ruby-gemset"
178
- - ".ruby-version"
179
181
  - CHANGELOG.md
180
182
  - Gemfile
181
183
  - MIT-LICENSE
@@ -184,6 +186,8 @@ files:
184
186
  - lib/sidekiq-bus.rb
185
187
  - lib/sidekiq_bus/adapter.rb
186
188
  - lib/sidekiq_bus/middleware/retry.rb
189
+ - lib/sidekiq_bus/server.rb
190
+ - lib/sidekiq_bus/server/views/bus.erb
187
191
  - lib/sidekiq_bus/tasks.rb
188
192
  - lib/sidekiq_bus/version.rb
189
193
  - sidekiq-bus.gemspec
@@ -209,7 +213,6 @@ files:
209
213
  homepage: https://github.com/queue-bus/sidekiq-bus
210
214
  licenses: []
211
215
  metadata: {}
212
- post_install_message:
213
216
  rdoc_options: []
214
217
  require_paths:
215
218
  - lib
@@ -224,9 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
227
  - !ruby/object:Gem::Version
225
228
  version: '0'
226
229
  requirements: []
227
- rubyforge_project:
228
- rubygems_version: 2.5.2
229
- signing_key:
230
+ rubygems_version: 3.6.6
230
231
  specification_version: 4
231
232
  summary: A simple event bus on top of Sidekiq
232
233
  test_files:
data/.rbenv-version DELETED
@@ -1 +0,0 @@
1
- 2.3.4
data/.ruby-gemset DELETED
@@ -1,2 +0,0 @@
1
- sidekiq-bus
2
-
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.3.4