protobuf-nats 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1a5657826a433d857f0b08fa99f314df065af9be
4
- data.tar.gz: 0f4a0ec4a8c239e595251c2894f6e7d7bca8419a
3
+ metadata.gz: df808ca99a789024cfe3ab03071d1acafeef32a5
4
+ data.tar.gz: 6ba58e9150dd5b575a3b2b44e1f6ff06ff151681
5
5
  SHA512:
6
- metadata.gz: 541b8c84ffe66f575447b69c84198ed3eedebd996879fa9dc75b3ac210ed899dc526626d7a31f0a526ec68a8407f6a19d69248e6fb7dd4845ef2fc5d41e706a9
7
- data.tar.gz: 34e7f770187a6d14d3d88aa4637688c8a5c4fd48e6fcf9dbf7f1a635a3fe0c9e739ecabcb6ccee6c8f0db34a188f58632cff4cf56b06a5fa6459bcbe84393214
6
+ metadata.gz: 648a3e8de0b1ca89864eaef8b5076d25eb74508920c31d04883b1766bf09d6237aac15b3b55ba3b5e126d51ebc063468ebbdb92278a33ac8dd953e9c85e7b1ba
7
+ data.tar.gz: f4dba8e3b094b0e2f19a89d436ed209f792cd3696d07d6c6c931352202aceec5961980be83e45708d2a39c3d091e99754b3179f3776d0934464de44933c64627
data/README.md CHANGED
@@ -38,6 +38,11 @@ used to allow JVM based servers to warm-up slowly to prevent jolts in runtime pe
38
38
 
39
39
  `PB_NATS_CLIENT_ACK_TIMEOUT` - Seconds to wait for an ACK from the rpc server (default: 5 seconds).
40
40
 
41
+ `PB_NATS_CLIENT_NACK_BACKOFF_INTERVALS` - Array of milliseconds to wait between NACK retries (default: "0,1,3,5,10").
42
+
43
+ `PB_NATS_CLIENT_NACK_BACKOFF_SPLAY_LIMIT` - Milliseconds to add to the NACK backoff timeout to avoid bursting retries
44
+ (default: 10 milliseconds).
45
+
41
46
  `PB_NATS_CLIENT_RESPONSE_TIMEOUT` - Seconds to wait for a non-ACK response from the rpc server (default: 60 seconds).
42
47
 
43
48
  `PB_NATS_CLIENT_RECONNECT_DELAY` - If we detect a reconnect delay, we will wait this many seconds (default: the ACK timeout).
data/lib/protobuf/nats.rb CHANGED
@@ -19,7 +19,8 @@ module Protobuf
19
19
  end
20
20
 
21
21
  module Messages
22
- ACK = "\1".freeze
22
+ ACK = "\1".freeze
23
+ NACK = "\2".freeze
23
24
  end
24
25
 
25
26
  NatsClient = if defined? JRUBY_VERSION
@@ -29,6 +29,30 @@ module Protobuf
29
29
  end
30
30
  end
31
31
 
32
+ def nack_backoff_intervals
33
+ @nack_backoff_intervals ||= if ::ENV.key?("PB_NATS_CLIENT_NACK_BACKOFF_INTERVALS")
34
+ ::ENV["PB_NATS_CLIENT_NACK_BACKOFF_INTERVALS"].split(",").map(&:to_i)
35
+ else
36
+ [0, 1, 3, 5, 10]
37
+ end
38
+ end
39
+
40
+ def nack_backoff_splay
41
+ @nack_backoff_splay ||= if nack_backoff_splay_limit > 0
42
+ rand(nack_backoff_splay_limit)
43
+ else
44
+ 0
45
+ end
46
+ end
47
+
48
+ def nack_backoff_splay_limit
49
+ @nack_backoff_splay_limit ||= if ::ENV.key?("PB_NATS_CLIENT_NACK_BACKOFF_SPLAY_LIMIT")
50
+ ::ENV["PB_NATS_CLIENT_NACK_BACKOFF_SPLAY_LIMIT"].to_i
51
+ else
52
+ 10
53
+ end
54
+ end
55
+
32
56
  def reconnect_delay
33
57
  @reconnect_delay ||= if ::ENV.key?("PB_NATS_CLIENT_RECONNECT_DELAY")
34
58
  ::ENV["PB_NATS_CLIENT_RECONNECT_DELAY"].to_i
@@ -47,11 +71,28 @@ module Protobuf
47
71
 
48
72
  def send_request
49
73
  retries ||= 3
74
+ nack_retry ||= 0
75
+
76
+ loop do
77
+ setup_connection
78
+ request_options = {:timeout => response_timeout, :ack_timeout => ack_timeout}
79
+ @response_data = nats_request_with_two_responses(cached_subscription_key, @request_data, request_options)
80
+ case @response_data
81
+ when :ack_timeout
82
+ next if (retries -= 1) > 0
83
+ raise ::NATS::IO::Timeout
84
+ when :nack
85
+ interval = nack_backoff_intervals[nack_retry]
86
+ nack_retry += 1
87
+ raise ::NATS::IO::Timeout if interval.nil?
88
+ sleep((interval + nack_backoff_splay)/1000.0)
89
+ next
90
+ end
91
+ break
92
+ end
50
93
 
51
- setup_connection
52
- request_options = {:timeout => response_timeout, :ack_timeout => ack_timeout}
53
- @response_data = nats_request_with_two_responses(cached_subscription_key, @request_data, request_options)
54
94
  parse_response
95
+
55
96
  rescue ::Protobuf::Nats::Errors::IOException => error
56
97
  ::Protobuf::Nats.log_error(error)
57
98
 
@@ -59,10 +100,6 @@ module Protobuf
59
100
  logger.warn "An IOException was raised. We are going to sleep for #{delay} seconds."
60
101
  sleep delay
61
102
 
62
- retry if (retries -= 1) > 0
63
- raise
64
- rescue ::NATS::IO::Timeout
65
- # Nats response timeout.
66
103
  retry if (retries -= 1) > 0
67
104
  raise
68
105
  end
@@ -100,24 +137,19 @@ module Protobuf
100
137
 
101
138
  # Wait for reply
102
139
  first_message = nats.next_message(sub, ack_timeout)
103
- fail ::NATS::IO::Timeout if first_message.nil?
140
+ return :ack_timeout if first_message.nil?
141
+ return :nack if first_message.data == ::Protobuf::Nats::Messages::NACK
142
+
104
143
  second_message = nats.next_message(sub, timeout)
105
- fail ::NATS::IO::Timeout if second_message.nil?
144
+ fail(::NATS::IO::Timeout, subject) if second_message.nil?
106
145
 
107
146
  # Check messages
108
- response = nil
109
- has_ack = false
110
- case first_message.data
111
- when ::Protobuf::Nats::Messages::ACK then has_ack = true
112
- else response = first_message.data
113
- end
114
- case second_message.data
115
- when ::Protobuf::Nats::Messages::ACK then has_ack = true
116
- else response = second_message.data
117
- end
147
+ response = case ::Protobuf::Nats::Messages::ACK
148
+ when first_message.data then second_message.data
149
+ when second_message.data then first_message.data
150
+ end
118
151
 
119
- success = has_ack && response
120
- fail(::NATS::IO::Timeout, subject) unless success
152
+ fail(::NATS::IO::Timeout, subject) unless response
121
153
 
122
154
  response
123
155
  ensure
@@ -131,19 +163,16 @@ module Protobuf
131
163
  nats = Protobuf::Nats.client_nats_connection
132
164
  inbox = nats.new_inbox
133
165
  lock = ::Monitor.new
134
- ack_condition = lock.new_cond
135
- pb_response_condition = lock.new_cond
166
+ received = lock.new_cond
167
+ messages = []
168
+ first_message = nil
169
+ second_message = nil
136
170
  response = nil
171
+
137
172
  sid = nats.subscribe(inbox, :max => 2) do |message, _, _|
138
173
  lock.synchronize do
139
- case message
140
- when ::Protobuf::Nats::Messages::ACK
141
- ack_condition.signal
142
- next
143
- else
144
- response = message
145
- pb_response_condition.signal
146
- end
174
+ messages << message
175
+ received.signal
147
176
  end
148
177
  end
149
178
 
@@ -153,28 +182,31 @@ module Protobuf
153
182
 
154
183
  # Wait for the ACK from the server
155
184
  ack_timeout = opts[:ack_timeout] || 5
156
- with_timeout(ack_timeout) { ack_condition.wait(ack_timeout) }
185
+ received.wait(ack_timeout) if messages.empty?
186
+ first_message = messages.shift
187
+
188
+ return :ack_timeout if first_message.nil?
189
+ return :nack if first_message == ::Protobuf::Nats::Messages::NACK
157
190
 
158
191
  # Wait for the protobuf response
159
192
  timeout = opts[:timeout] || 60
160
- with_timeout(timeout) { pb_response_condition.wait(timeout) } unless response
193
+ received.wait(timeout) if messages.empty?
194
+ second_message = messages.shift
161
195
  end
162
196
 
197
+ response = case ::Protobuf::Nats::Messages::ACK
198
+ when first_message then second_message
199
+ when second_message then first_message
200
+ end
201
+
202
+ fail(::NATS::IO::Timeout, subject) unless response
203
+
163
204
  response
164
205
  ensure
165
206
  # Ensure we don't leave a subscription sitting around.
166
207
  nats.unsubscribe(sid) if response.nil?
167
208
  end
168
209
 
169
- # This is a copy of #with_nats_timeout
170
- def with_timeout(timeout)
171
- start_time = ::NATS::MonotonicTime.now
172
- yield
173
- end_time = ::NATS::MonotonicTime.now
174
- duration = end_time - start_time
175
- raise ::NATS::IO::Timeout.new("nats: timeout") if duration > timeout
176
- end
177
-
178
210
  end
179
211
 
180
212
  end
@@ -55,7 +55,12 @@ module Protobuf
55
55
  end
56
56
 
57
57
  # Publish an ACK to signal the server has picked up the work.
58
- nats.publish(reply_id, ::Protobuf::Nats::Messages::ACK) if was_enqueued
58
+ if was_enqueued
59
+ nats.publish(reply_id, ::Protobuf::Nats::Messages::ACK)
60
+ else
61
+ # TODO: Uncomment once we can roll out NACK messages without a 60 second timeout
62
+ # nats.publish(reply_id, ::Protobuf::Nats::Messages::NACK)
63
+ end
59
64
 
60
65
  was_enqueued
61
66
  end
@@ -1,5 +1,5 @@
1
1
  module Protobuf
2
2
  module Nats
3
- VERSION = "0.5.0"
3
+ VERSION = "0.5.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protobuf-nats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Dewitt
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-26 00:00:00.000000000 Z
11
+ date: 2017-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: protobuf