message_bus 2.0.6 → 2.0.7

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e3233d29ea9404805798a4b1a4caddf2a50477c
4
- data.tar.gz: f77eed645f31f2182dc28d94fdf80dc8746ffffd
3
+ metadata.gz: 6261c99f5e5950c4d602faeb54aa133b747075e1
4
+ data.tar.gz: e6318de70431d0ca0ed84efb14c54379bcccf527
5
5
  SHA512:
6
- metadata.gz: 4a1b8e23c41ea624f21012e8c9f83be06217d1cfb103dd5c13417aff52bf49fab6dde813185f5186b8bdd226267bd5ac2aec859cdd49c35323e35f8c51a8af57
7
- data.tar.gz: b1285bcba99c5263eba003781a8423245d198edb88bf2c1265d895a771d6b75bc1da89e119cb973d08a58fa4c98726d9bb75ed425c8b28f089c5fdbed70db8f1
6
+ metadata.gz: 3f6a1cd06d53694cf1ccdc7455f1d3adbdee5c2f09ce9b38cd9cec5a26128b1d979b35dea9f3add98143554620171118508d560c057e3380a5c9880a9225348e
7
+ data.tar.gz: bf4373a4595e43ba6adb59cd3e8046c190a039a055af657fa05fa2f224914a1461c1f0dec30e1ce708fe8c9d518180563270b0fbf9455e5039ffda4379b14b9a
data/.travis.yml CHANGED
@@ -1,7 +1,6 @@
1
1
  before_install: gem install bundler
2
2
  language: ruby
3
3
  rvm:
4
- - 1.9.3
5
4
  - 2.0.0
6
5
  - 2.1.8
7
6
  - 2.2.4
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ 02-10-2017
2
+
3
+ - Version 2.0.7
4
+
5
+ - Fix/Feature: use LUA script for publishing to bus, this eliminates a race condition
6
+ and ensures that we are never stuck in a multi transaction by mistake
7
+
8
+
1
9
  29-09-2017
2
10
 
3
11
  - Version 2.0.6
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
+ #
2
3
  require 'redis'
4
+ require 'digest'
5
+
3
6
  # the heart of the message bus, it acts as 2 things
4
7
  #
5
8
  # 1. A channel multiplexer
@@ -81,46 +84,70 @@ class MessageBus::Redis::ReliablePubSub
81
84
  end
82
85
  end
83
86
 
84
- def publish(channel, data, queue_in_memory = true)
85
- redis = pub_redis
86
- backlog_id_key = backlog_id_key(channel)
87
- backlog_key = backlog_key(channel)
87
+ LUA_PUBLISH = <<LUA
88
88
 
89
- global_id = nil
90
- backlog_id = nil
89
+ local start_payload = ARGV[1]
90
+ local max_backlog_age = ARGV[2]
91
+ local max_backlog_size = tonumber(ARGV[3])
92
+ local max_global_backlog_size = tonumber(ARGV[4])
93
+ local channel = ARGV[5]
91
94
 
92
- redis.multi do |m|
93
- global_id = m.incr(global_id_key)
94
- backlog_id = m.incr(backlog_id_key)
95
- end
95
+ local global_id_key = KEYS[1]
96
+ local backlog_id_key = KEYS[2]
97
+ local backlog_key = KEYS[3]
98
+ local global_backlog_key = KEYS[4]
99
+ local redis_channel_name = KEYS[5]
96
100
 
97
- global_id = global_id.value
98
- backlog_id = backlog_id.value
101
+ local global_id = redis.call("INCR", global_id_key)
102
+ local backlog_id = redis.call("INCR", backlog_id_key)
103
+ local payload = string.format("%i|%i|%s", global_id, backlog_id, start_payload)
104
+ local global_backlog_message = string.format("%i|%s", backlog_id, channel)
99
105
 
100
- msg = MessageBus::Message.new global_id, backlog_id, channel, data
101
- payload = msg.encode
106
+ redis.call("ZADD", backlog_key, backlog_id, payload)
107
+ redis.call("EXPIRE", backlog_key, max_backlog_age)
102
108
 
103
- redis.multi do |m|
109
+ redis.call("ZADD", global_backlog_key, global_id, global_backlog_message)
110
+ redis.call("EXPIRE", global_backlog_key, max_backlog_age)
104
111
 
105
- redis.zadd backlog_key, backlog_id, payload
106
- redis.expire backlog_key, @max_backlog_age
112
+ redis.call("PUBLISH", redis_channel_name, payload)
107
113
 
108
- redis.zadd global_backlog_key, global_id, backlog_id.to_s << "|" << channel
109
- redis.expire global_backlog_key, @max_backlog_age
114
+ if backlog_id > max_backlog_size then
115
+ redis.call("ZREMRANGEBYSCORE", backlog_key, 1, backlog_id - max_backlog_size)
116
+ end
110
117
 
111
- redis.publish redis_channel_name, payload
118
+ if global_id > max_global_backlog_size then
119
+ redis.call("ZREMRANGEBYSCORE", global_backlog_key, 1, global_id - max_global_backlog_size)
120
+ end
112
121
 
113
- if backlog_id > @max_backlog_size
114
- redis.zremrangebyscore backlog_key, 1, backlog_id - @max_backlog_size
115
- end
122
+ return backlog_id
116
123
 
117
- if global_id > @max_global_backlog_size
118
- redis.zremrangebyscore global_backlog_key, 1, global_id - @max_global_backlog_size
119
- end
124
+ LUA
120
125
 
121
- end
126
+ LUA_PUBLISH_SHA1 = Digest::SHA1.hexdigest(LUA_PUBLISH)
122
127
 
123
- backlog_id
128
+ def publish(channel, data, queue_in_memory = true)
129
+ redis = pub_redis
130
+ backlog_id_key = backlog_id_key(channel)
131
+ backlog_key = backlog_key(channel)
132
+
133
+ msg = MessageBus::Message.new nil, nil, channel, data
134
+
135
+ cached_eval(redis, LUA_PUBLISH, LUA_PUBLISH_SHA1,
136
+ argv: [
137
+ msg.encode_without_ids,
138
+ max_backlog_age,
139
+ max_backlog_size,
140
+ max_global_backlog_size,
141
+ channel
142
+ ],
143
+ keys: [
144
+ global_id_key,
145
+ backlog_id_key,
146
+ backlog_key,
147
+ global_backlog_key,
148
+ redis_channel_name
149
+ ]
150
+ )
124
151
 
125
152
  rescue Redis::CommandError => e
126
153
  if queue_in_memory && e.message =~ /^READONLY/
@@ -342,6 +369,18 @@ class MessageBus::Redis::ReliablePubSub
342
369
 
343
370
  private
344
371
 
372
+ def cached_eval(redis, script, script_sha1, params)
373
+ begin
374
+ redis.evalsha script_sha1, params
375
+ rescue Redis::CommandError => e
376
+ if e.to_s =~ /^NOSCRIPT/
377
+ redis.eval script, params
378
+ else
379
+ raise
380
+ end
381
+ end
382
+ end
383
+
345
384
  def is_readonly?
346
385
  key = "__mb_is_readonly"
347
386
 
@@ -17,4 +17,8 @@ class MessageBus::Message < Struct.new(:global_id, :message_id, :channel , :data
17
17
  def encode
18
18
  global_id.to_s << "|" << message_id.to_s << "|" << channel.gsub("|", "$$123$$") << "|" << data
19
19
  end
20
+
21
+ def encode_without_ids
22
+ channel.gsub("|", "$$123$$") << "|" << data
23
+ end
20
24
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module MessageBus
3
- VERSION = "2.0.6"
3
+ VERSION = "2.0.7"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: message_bus
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.6
4
+ version: 2.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-29 00:00:00.000000000 Z
11
+ date: 2017-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack