message_bus 2.0.6 → 2.0.7

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.

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