message_bus 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of message_bus might be problematic. Click here for more details.

@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pg'
2
3
 
3
4
  module MessageBus::Postgres; end
@@ -30,37 +31,41 @@ class MessageBus::Postgres::Client
30
31
  @pid = Process.pid
31
32
  end
32
33
 
33
- def add(channel, value)
34
- hold{|conn| exec_prepared(conn, 'insert_message', [channel, value]){|r| r.getvalue(0,0).to_i}}
34
+ def add (channel, value)
35
+ hold { |conn| exec_prepared(conn, 'insert_message', [channel, value]) { |r| r.getvalue(0, 0).to_i } }
35
36
  end
36
37
 
37
38
  def clear_global_backlog(backlog_id, num_to_keep)
38
39
  if backlog_id > num_to_keep
39
- hold{|conn| exec_prepared(conn, 'clear_global_backlog', [backlog_id - num_to_keep])}
40
+ hold { |conn| exec_prepared(conn, 'clear_global_backlog', [backlog_id - num_to_keep]) }
40
41
  nil
41
42
  end
42
43
  end
43
44
 
44
45
  def clear_channel_backlog(channel, backlog_id, num_to_keep)
45
- hold{|conn| exec_prepared(conn, 'clear_channel_backlog', [channel, backlog_id, num_to_keep])}
46
+ hold { |conn| exec_prepared(conn, 'clear_channel_backlog', [channel, backlog_id, num_to_keep]) }
46
47
  nil
47
48
  end
48
49
 
49
50
  def expire(max_backlog_age)
50
- hold{|conn| exec_prepared(conn, 'expire', [max_backlog_age])}
51
+ hold { |conn| exec_prepared(conn, 'expire', [max_backlog_age]) }
51
52
  nil
52
53
  end
53
54
 
54
55
  def backlog(channel, backlog_id)
55
- hold{|conn| exec_prepared(conn, 'channel_backlog', [channel, backlog_id]){|r| r.values.each{|a| a[0] = a[0].to_i}}} || []
56
+ hold do |conn|
57
+ exec_prepared(conn, 'channel_backlog', [channel, backlog_id]) { |r| r.values.each { |a| a[0] = a[0].to_i } }
58
+ end || []
56
59
  end
57
60
 
58
61
  def global_backlog(backlog_id)
59
- hold{|conn| exec_prepared(conn, 'global_backlog', [backlog_id]){|r| r.values.each{|a| a[0] = a[0].to_i}}} || []
62
+ hold do |conn|
63
+ exec_prepared(conn, 'global_backlog', [backlog_id]) { |r| r.values.each { |a| a[0] = a[0].to_i } }
64
+ end || []
60
65
  end
61
66
 
62
67
  def get_value(channel, id)
63
- hold{|conn| exec_prepared(conn, 'get_message', [channel, id]){|r| r.getvalue(0,0)}}
68
+ hold { |conn| exec_prepared(conn, 'get_message', [channel, id]) { |r| r.getvalue(0, 0) } }
64
69
  end
65
70
 
66
71
  def reconnect
@@ -78,37 +83,37 @@ class MessageBus::Postgres::Client
78
83
  end
79
84
  end
80
85
 
81
- def max_id(channel=nil)
86
+ def max_id(channel = nil)
82
87
  block = proc do |r|
83
88
  if r.ntuples > 0
84
- r.getvalue(0,0).to_i
89
+ r.getvalue(0, 0).to_i
85
90
  else
86
91
  0
87
92
  end
88
93
  end
89
94
 
90
95
  if channel
91
- hold{|conn| exec_prepared(conn, 'max_channel_id', [channel], &block)}
96
+ hold { |conn| exec_prepared(conn, 'max_channel_id', [channel], &block) }
92
97
  else
93
- hold{|conn| exec_prepared(conn, 'max_id', &block)}
98
+ hold { |conn| exec_prepared(conn, 'max_id', &block) }
94
99
  end
95
100
  end
96
101
 
97
102
  def publish(channel, data)
98
- hold{|conn| exec_prepared(conn, 'publish', [channel, data])}
103
+ hold { |conn| exec_prepared(conn, 'publish', [channel, data]) }
99
104
  end
100
105
 
101
106
  def subscribe(channel)
102
107
  obj = Object.new
103
- sync{@listening_on[channel] = obj}
108
+ sync { @listening_on[channel] = obj }
104
109
  listener = Listener.new
105
110
  yield listener
106
-
111
+
107
112
  conn = raw_pg_connection
108
113
  conn.exec "LISTEN #{channel}"
109
114
  listener.do_sub.call
110
115
  while listening_on?(channel, obj)
111
- conn.wait_for_notify(10) do |_,_,payload|
116
+ conn.wait_for_notify(10) do |_, _, payload|
112
117
  break unless listening_on?(channel, obj)
113
118
  listener.do_message.call(nil, payload)
114
119
  end
@@ -120,7 +125,7 @@ class MessageBus::Postgres::Client
120
125
  end
121
126
 
122
127
  def unsubscribe
123
- sync{@listening_on.clear}
128
+ sync { @listening_on.clear }
124
129
  end
125
130
 
126
131
  private
@@ -149,22 +154,22 @@ class MessageBus::Postgres::Client
149
154
  end
150
155
  end
151
156
 
152
- if conn = sync{@allocated[Thread.current]}
157
+ if conn = sync { @allocated[Thread.current] }
153
158
  return yield(conn)
154
159
  end
155
-
160
+
156
161
  begin
157
- conn = sync{@available.shift} || new_pg_connection
158
- sync{@allocated[Thread.current] = conn}
162
+ conn = sync { @available.shift } || new_pg_connection
163
+ sync { @allocated[Thread.current] = conn }
159
164
  yield conn
160
165
  rescue PG::ConnectionBad, PG::UnableToSend => e
161
166
  # don't add this connection back to the pool
162
167
  ensure
163
- sync{@allocated.delete(Thread.current)}
168
+ sync { @allocated.delete(Thread.current) }
164
169
  if Process.pid != current_pid
165
- sync{INHERITED_CONNECTIONS << conn}
170
+ sync { INHERITED_CONNECTIONS << conn }
166
171
  elsif conn && !e
167
- sync{@available << conn}
172
+ sync { @available << conn }
168
173
  end
169
174
  end
170
175
  end
@@ -197,11 +202,11 @@ class MessageBus::Postgres::Client
197
202
  end
198
203
 
199
204
  def listening_on?(channel, obj)
200
- sync{@listening_on[channel]} == obj
205
+ sync { @listening_on[channel] } == obj
201
206
  end
202
207
 
203
208
  def sync
204
- @mutex.synchronize{yield}
209
+ @mutex.synchronize { yield }
205
210
  end
206
211
  end
207
212
 
@@ -251,7 +256,7 @@ class MessageBus::Postgres::ReliablePubSub
251
256
  client.reset!
252
257
  end
253
258
 
254
- def publish(channel, data, queue_in_memory=true)
259
+ def publish(channel, data, queue_in_memory = true)
255
260
  client = self.client
256
261
  backlog_id = client.add(channel, data)
257
262
  msg = MessageBus::Message.new backlog_id, backlog_id, channel, data
@@ -322,7 +327,7 @@ class MessageBus::Postgres::ReliablePubSub
322
327
  @subscribed = false
323
328
  end
324
329
 
325
- def global_subscribe(last_id=nil, &blk)
330
+ def global_subscribe(last_id = nil, &blk)
326
331
  raise ArgumentError unless block_given?
327
332
  highest_id = last_id
328
333
 
@@ -345,7 +350,7 @@ class MessageBus::Postgres::ReliablePubSub
345
350
  @subscribed = false
346
351
  end
347
352
 
348
- on.message do |c,m|
353
+ on.message do |c, m|
349
354
  if m == UNSUB_MESSAGE
350
355
  @subscribed = false
351
356
  return
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'redis'
2
3
  # the heart of the message bus, it acts as 2 things
3
4
  #
@@ -80,7 +81,7 @@ class MessageBus::Redis::ReliablePubSub
80
81
  end
81
82
  end
82
83
 
83
- def publish(channel, data, queue_in_memory=true)
84
+ def publish(channel, data, queue_in_memory = true)
84
85
  redis = pub_redis
85
86
  backlog_id_key = backlog_id_key(channel)
86
87
  backlog_key = backlog_key(channel)
@@ -122,21 +123,19 @@ class MessageBus::Redis::ReliablePubSub
122
123
  backlog_id
123
124
 
124
125
  rescue Redis::CommandError => e
125
- if queue_in_memory &&
126
- e.message =~ /^READONLY/
127
-
126
+ if queue_in_memory && e.message =~ /^READONLY/
128
127
  @lock.synchronize do
129
- @in_memory_backlog << [channel,data]
128
+ @in_memory_backlog << [channel, data]
130
129
  if @in_memory_backlog.length > @max_in_memory_publish_backlog
131
130
  @in_memory_backlog.delete_at(0)
132
- MessageBus.logger.warn("Dropping old message cause max_in_memory_publish_backlog is full")
131
+ MessageBus.logger.warn("Dropping old message cause max_in_memory_publish_backlog is full: #{e.message}\n#{e.backtrace.join('\n')}")
133
132
  end
134
133
  end
135
134
 
136
135
  if @flush_backlog_thread == nil
137
136
  @lock.synchronize do
138
137
  if @flush_backlog_thread == nil
139
- @flush_backlog_thread = Thread.new{ensure_backlog_flushed}
138
+ @flush_backlog_thread = Thread.new { ensure_backlog_flushed }
140
139
  end
141
140
  end
142
141
  end
@@ -164,15 +163,15 @@ class MessageBus::Redis::ReliablePubSub
164
163
  end
165
164
 
166
165
  begin
167
- publish(*@in_memory_backlog[0],false)
166
+ publish(*@in_memory_backlog[0], false)
168
167
  rescue Redis::CommandError => e
169
168
  if e.message =~ /^READONLY/
170
169
  try_again = true
171
170
  else
172
- MessageBus.logger.warn("Dropping undeliverable message #{e}")
171
+ MessageBus.logger.warn("Dropping undeliverable message: #{e.message}\n#{e.backtrace.join('\n')}")
173
172
  end
174
173
  rescue => e
175
- MessageBus.logger.warn("Dropping undeliverable message #{e}")
174
+ MessageBus.logger.warn("Dropping undeliverable message: #{e.message}\n#{e.backtrace.join('\n')}")
176
175
  end
177
176
 
178
177
  @in_memory_backlog.delete_at(0) unless try_again
@@ -208,7 +207,7 @@ class MessageBus::Redis::ReliablePubSub
208
207
  items.map! do |i|
209
208
  pipe = i.index "|"
210
209
  message_id = i[0..pipe].to_i
211
- channel = i[pipe+1..-1]
210
+ channel = i[pipe + 1..-1]
212
211
  m = get_message(channel, message_id)
213
212
  m
214
213
  end
@@ -277,7 +276,7 @@ class MessageBus::Redis::ReliablePubSub
277
276
  end
278
277
  end
279
278
 
280
- def global_subscribe(last_id=nil, &blk)
279
+ def global_subscribe(last_id = nil, &blk)
281
280
  raise ArgumentError unless block_given?
282
281
  highest_id = last_id
283
282
 
@@ -293,7 +292,6 @@ class MessageBus::Redis::ReliablePubSub
293
292
  end
294
293
  end
295
294
 
296
-
297
295
  begin
298
296
  @redis_global = new_redis_connection
299
297
 
@@ -313,7 +311,7 @@ class MessageBus::Redis::ReliablePubSub
313
311
  @subscribed = false
314
312
  end
315
313
 
316
- on.message do |c,m|
314
+ on.message do |c, m|
317
315
  if m == UNSUB_MESSAGE
318
316
  @redis_global.unsubscribe
319
317
  return
@@ -344,7 +342,7 @@ class MessageBus::Redis::ReliablePubSub
344
342
  private
345
343
 
346
344
  def is_readonly?
347
- key = "__mb_is_readonly".freeze
345
+ key = "__mb_is_readonly"
348
346
 
349
347
  begin
350
348
  # in case we are not connected to the correct server
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class MessageBus::Client
2
3
  attr_accessor :client_id, :user_id, :group_ids, :connect_time,
3
4
  :subscribed_sets, :site_id, :cleanup_timer,
@@ -45,21 +46,21 @@ class MessageBus::Client
45
46
 
46
47
  def ensure_first_chunk_sent
47
48
  if use_chunked && @chunks_sent == 0
48
- write_chunk("[]".freeze)
49
+ write_chunk("[]")
49
50
  end
50
51
  end
51
52
 
52
53
  def ensure_closed!
53
54
  return unless in_async?
54
55
  if use_chunked
55
- write_chunk("[]".freeze)
56
+ write_chunk("[]")
56
57
  if @io
57
- @io.write("0\r\n\r\n".freeze)
58
+ @io.write("0\r\n\r\n")
58
59
  @io.close
59
60
  @io = nil
60
61
  end
61
62
  if @async_response
62
- @async_response << ("0\r\n\r\n".freeze)
63
+ @async_response << ("0\r\n\r\n")
63
64
  @async_response.done
64
65
  @async_response = nil
65
66
  end
@@ -117,21 +118,31 @@ class MessageBus::Client
117
118
 
118
119
  def backlog
119
120
  r = []
120
- @subscriptions.each do |k,v|
121
+ new_message_ids = nil
122
+
123
+ @subscriptions.each do |k, v|
121
124
  next if v.to_i < 0
122
125
  messages = @bus.backlog(k, v, site_id)
126
+
123
127
  messages.each do |msg|
124
- r << msg if allowed?(msg)
128
+ if allowed?(msg)
129
+ r << msg
130
+ else
131
+ new_message_ids ||= {}
132
+ new_message_ids[k] = msg.message_id
133
+ end
125
134
  end
126
135
  end
136
+
127
137
  # stats message for all newly subscribed
128
138
  status_message = nil
129
- @subscriptions.each do |k,v|
130
- if v.to_i == -1
139
+ @subscriptions.each do |k, v|
140
+ if v.to_i == -1 || (new_message_ids && new_message_ids[k])
131
141
  status_message ||= {}
132
142
  @subscriptions[k] = status_message[k] = @bus.last_id(k, site_id)
133
143
  end
134
144
  end
145
+
135
146
  r << MessageBus::Message.new(-1, -1, '/__status', status_message) if status_message
136
147
 
137
148
  r || []
@@ -139,9 +150,8 @@ class MessageBus::Client
139
150
 
140
151
  protected
141
152
 
142
-
143
153
  # heavily optimised to avoid all uneeded allocations
144
- NEWLINE="\r\n".freeze
154
+ NEWLINE = "\r\n".freeze
145
155
  COLON_SPACE = ": ".freeze
146
156
  HTTP_11 = "HTTP/1.1 200 OK\r\n".freeze
147
157
  CONTENT_LENGTH = "Content-Length: ".freeze
@@ -154,7 +164,7 @@ class MessageBus::Client
154
164
 
155
165
  def write_headers
156
166
  @io.write(HTTP_11)
157
- @headers.each do |k,v|
167
+ @headers.each do |k, v|
158
168
  next if k == "Content-Type"
159
169
  @io.write(k)
160
170
  @io.write(COLON_SPACE)
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require 'json' unless defined? ::JSON
2
3
 
3
4
  class MessageBus::ConnectionManager
4
5
  require 'monitor'
5
6
  include MonitorMixin
6
7
 
7
- def initialize(bus=nil)
8
+ def initialize(bus = nil)
8
9
  @clients = {}
9
10
  @subscriptions = {}
10
11
  @bus = bus || MessageBus
@@ -53,7 +54,7 @@ class MessageBus::ConnectionManager
53
54
 
54
55
  @clients[client.client_id] = client
55
56
  @subscriptions[client.site_id] ||= {}
56
- client.subscriptions.each do |k,v|
57
+ client.subscriptions.each do |k, v|
57
58
  subscribe_client(client, k)
58
59
  end
59
60
  end
@@ -79,7 +80,7 @@ class MessageBus::ConnectionManager
79
80
  end
80
81
  end
81
82
 
82
- def subscribe_client(client,channel)
83
+ def subscribe_client(client, channel)
83
84
  synchronize do
84
85
  set = @subscriptions[client.site_id][channel]
85
86
  unless set
@@ -1,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class MessageBus::Message < Struct.new(:global_id, :message_id, :channel , :data)
2
4
 
3
5
  attr_accessor :site_id, :user_ids, :group_ids, :client_ids
4
6
 
5
7
  def self.decode(encoded)
6
8
  s1 = encoded.index("|")
7
- s2 = encoded.index("|", s1+1)
8
- s3 = encoded.index("|", s2+1)
9
+ s2 = encoded.index("|", s1 + 1)
10
+ s3 = encoded.index("|", s2 + 1)
9
11
 
10
- MessageBus::Message.new(encoded[0..s1].to_i, encoded[s1+1..s2].to_i,
11
- encoded[s2+1..s3-1].gsub("$$123$$", "|"), encoded[s3+1..-1])
12
+ MessageBus::Message.new(encoded[0..s1].to_i, encoded[(s1 + 1)..s2].to_i,
13
+ encoded[(s2 + 1)..(s3 - 1)].gsub("$$123$$", "|"), encoded[(s3 + 1)..-1])
12
14
  end
13
15
 
14
16
  # only tricky thing to encode is pipes in a channel name ... do a straight replace
15
17
  def encode
16
- global_id.to_s << "|" << message_id.to_s << "|" << channel.gsub("|","$$123$$") << "|" << data
18
+ global_id.to_s << "|" << message_id.to_s << "|" << channel.gsub("|", "$$123$$") << "|" << data
17
19
  end
18
20
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module MessageBus::Rack; end
2
3
 
3
4
  class MessageBus::Rack::Diagnostics
@@ -48,7 +49,7 @@ class MessageBus::Rack::Diagnostics
48
49
  </body>
49
50
  </html>
50
51
  HTML
51
- return [200, {"content-type" => "text/html;"}, [html]]
52
+ return [200, { "content-type" => "text/html;" }, [html]]
52
53
  end
53
54
 
54
55
  def translate_handlebars(name, content)
@@ -80,7 +81,7 @@ HTML
80
81
 
81
82
  if route =~ /^\/hup\//
82
83
  hostname, pid = route.split('/hup/')[1].split('/')
83
- @bus.publish('/_diagnostics/hup', {hostname: hostname, pid: pid.to_i})
84
+ @bus.publish('/_diagnostics/hup', hostname: hostname, pid: pid.to_i)
84
85
  return [200, {}, ['ok']]
85
86
  end
86
87
 
@@ -89,9 +90,9 @@ HTML
89
90
  content = asset_contents(asset)
90
91
  split = asset.split('.')
91
92
  if split[1] == 'handlebars'
92
- content = translate_handlebars(split[0],content)
93
+ content = translate_handlebars(split[0], content)
93
94
  end
94
- return [200, {'content-type' => 'text/javascript;'}, [content]]
95
+ return [200, { 'content-type' => 'text/javascript;' }, [content]]
95
96
  end
96
97
 
97
98
  return [404, {}, ['not found']]