nats-pure 0.4.0 → 0.5.0

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
  SHA256:
3
- metadata.gz: 59129f0c5e0180f95490a2ca5e2acb8cf0c1d630c32e4d4ab6f0cf859242500b
4
- data.tar.gz: c23db05317523a59762b9b2e73917165baf8ee3a898aaa74e84a74b0977c1942
3
+ metadata.gz: 741d87f63f2851dc25639453f9cd5ed68b3e2bfb66f45f1b5fe6caa9b3e352dd
4
+ data.tar.gz: 1af44d28a31788e37fbb50d14f966ff30805ee42614ae37a7ab3599edd0de4f0
5
5
  SHA512:
6
- metadata.gz: b82fdc592bea6ddc5ca1e0792b76071dd09db70a86fcaef517207d33c339d1b105076efd2b3d3cc83960a6b470739d01ec9d2f41574f57111935e0245eb02e5d
7
- data.tar.gz: 4439c2f2f0c3c6118b5a4b93587a60ecb069f8b85e0907539bec6a497a8394a1f78a9a961aa2565436e7c7ab4ee3bc1bd459310935499da67c1d7e7c11a0d5c7
6
+ metadata.gz: 432d3b3cf28752ec19c6278763ec5e1ef5992ee9d57796aeadb41b978028b3700c699795134f46297c982d9fc98fc3979d0760842f74fb528977e62b66431c9c
7
+ data.tar.gz: 758a3b3deb4c2b14198bca42b647d2b11726c08d7150a914a8835a64fa6720d57d28c2207ddcd6ad40995427902ab1afd6705f2ab4c4ea1adbe9e131ccc1ea32
@@ -1,5 +1,20 @@
1
+ # Copyright 2016-2018 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
1
15
  require 'nats/io/parser'
2
16
  require 'nats/io/version'
17
+ require 'nats/nuid'
3
18
  require 'thread'
4
19
  require 'socket'
5
20
  require 'json'
@@ -159,13 +174,20 @@ module NATS
159
174
  # Hostname of current server; used for when TLS host
160
175
  # verification is enabled.
161
176
  @hostname = nil
177
+
178
+ # New style request/response implementation.
179
+ @resp_sub = nil
180
+ @resp_map = nil
181
+ @resp_sub_prefix = nil
182
+ @nuid = NATS::NUID.new
162
183
  end
163
184
 
164
- # Establishes connection to NATS
185
+ # Establishes connection to NATS.
165
186
  def connect(opts={})
166
187
  opts[:verbose] = false if opts[:verbose].nil?
167
188
  opts[:pedantic] = false if opts[:pedantic].nil?
168
189
  opts[:reconnect] = true if opts[:reconnect].nil?
190
+ opts[:old_style_request] = false if opts[:old_style_request].nil?
169
191
  opts[:reconnect_time_wait] = RECONNECT_TIME_WAIT if opts[:reconnect_time_wait].nil?
170
192
  opts[:max_reconnect_attempts] = MAX_RECONNECT_ATTEMPTS if opts[:max_reconnect_attempts].nil?
171
193
  opts[:ping_interval] = DEFAULT_PING_INTERVAL if opts[:ping_interval].nil?
@@ -198,6 +220,12 @@ module NATS
198
220
  }
199
221
  end
200
222
 
223
+ if @options[:old_style_request]
224
+ # Replace for this instance the implementation
225
+ # of request to use the old_request style.
226
+ class << self; alias_method :request, :old_request; end
227
+ end
228
+
201
229
  # Check for TLS usage
202
230
  @tls = @options[:tls]
203
231
 
@@ -344,11 +372,58 @@ module NATS
344
372
  sid
345
373
  end
346
374
 
347
- # Sends a request expecting a single response or raises a timeout
348
- # in case the request is not retrieved within the specified deadline.
375
+ # Sends a request using expecting a single response using a
376
+ # single subscription per connection for receiving the responses.
377
+ # It times out in case the request is not retrieved within the
378
+ # specified deadline.
349
379
  # If given a callback, then the request happens asynchronously.
350
380
  def request(subject, payload, opts={}, &blk)
351
381
  return unless subject
382
+
383
+ # If a block was given then fallback to method using auto unsubscribe.
384
+ return old_request(subject, payload, opts, &blk) if blk
385
+
386
+ token = nil
387
+ inbox = nil
388
+ future = nil
389
+ response = nil
390
+ timeout = opts[:timeout] ||= 0.5
391
+ synchronize do
392
+ start_resp_mux_sub! unless @resp_sub_prefix
393
+
394
+ # Create token for this request.
395
+ token = @nuid.next
396
+ inbox = "#{@resp_sub_prefix}.#{token}"
397
+
398
+ # Create the a future for the request that will
399
+ # get signaled when it receives the request.
400
+ future = @resp_sub.new_cond
401
+ @resp_map[token][:future] = future
402
+ end
403
+
404
+ # Publish request and wait for reply.
405
+ publish(subject, payload, inbox)
406
+ with_nats_timeout(timeout) do
407
+ @resp_sub.synchronize do
408
+ future.wait(timeout)
409
+ end
410
+ end
411
+
412
+ # Check if there is a response already
413
+ synchronize do
414
+ result = @resp_map[token]
415
+ response = result[:response]
416
+ end
417
+
418
+ response
419
+ end
420
+
421
+ # Sends a request creating an ephemeral subscription for the request,
422
+ # expecting a single response or raising a timeout in case the request
423
+ # is not retrieved within the specified deadline.
424
+ # If given a callback, then the request happens asynchronously.
425
+ def old_request(subject, payload, opts={}, &blk)
426
+ return unless subject
352
427
  inbox = new_inbox
353
428
 
354
429
  # If a callback was passed, then have it process
@@ -520,7 +595,7 @@ module NATS
520
595
  future.signal
521
596
 
522
597
  return
523
- elsif sub.callback
598
+ elsif sub.pending_queue
524
599
  # Async subscribers use a sized queue for processing
525
600
  # and should be able to consume messages in parallel.
526
601
  if sub.pending_queue.size >= sub.pending_msgs_limit \
@@ -1093,6 +1168,47 @@ module NATS
1093
1168
  @ping_interval_thread.abort_on_exception = true
1094
1169
  end
1095
1170
 
1171
+ # Prepares requests subscription that handles the responses
1172
+ # for the new style request response.
1173
+ def start_resp_mux_sub!
1174
+ @resp_sub_prefix = "_INBOX.#{@nuid.next}"
1175
+ @resp_map = Hash.new { |h,k| h[k] = { }}
1176
+
1177
+ @resp_sub = Subscription.new
1178
+ @resp_sub.subject = "#{@resp_sub_prefix}.*"
1179
+ @resp_sub.received = 0
1180
+
1181
+ # FIXME: Allow setting pending limits for responses mux subscription.
1182
+ @resp_sub.pending_msgs_limit = DEFAULT_SUB_PENDING_MSGS_LIMIT
1183
+ @resp_sub.pending_bytes_limit = DEFAULT_SUB_PENDING_BYTES_LIMIT
1184
+ @resp_sub.pending_queue = SizedQueue.new(@resp_sub.pending_msgs_limit)
1185
+ @resp_sub.wait_for_msgs_t = Thread.new do
1186
+ loop do
1187
+ msg = @resp_sub.pending_queue.pop
1188
+ @resp_sub.pending_size -= msg.data.size
1189
+
1190
+ # Pick the token and signal the request under the mutex
1191
+ # from the subscription itself.
1192
+ token = msg.subject.split('.').last
1193
+ future = nil
1194
+ synchronize do
1195
+ future = @resp_map[token][:future]
1196
+ @resp_map[token][:response] = msg
1197
+ end
1198
+
1199
+ # Signal back that the response has arrived.
1200
+ @resp_sub.synchronize do
1201
+ future.signal
1202
+ end
1203
+ end
1204
+ end
1205
+
1206
+ sid = (@ssid += 1)
1207
+ @subs[sid] = @resp_sub
1208
+ send_command("SUB #{@resp_sub.subject} #{sid}#{CR_LF}")
1209
+ @flush_queue << :sub
1210
+ end
1211
+
1096
1212
  def can_reuse_server?(server)
1097
1213
  return false if server.nil?
1098
1214
 
@@ -1,3 +1,17 @@
1
+ # Copyright 2016-2018 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
1
15
  module NATS
2
16
  module Protocol
3
17
 
@@ -1,7 +1,21 @@
1
+ # Copyright 2016-2018 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
1
15
  module NATS
2
16
  module IO
3
17
  # NOTE: These are all announced to the server on CONNECT
4
- VERSION = "0.4.0"
18
+ VERSION = "0.5.0"
5
19
  LANG = "#{RUBY_ENGINE}2".freeze
6
20
  PROTOCOL = 1
7
21
  end
@@ -0,0 +1,81 @@
1
+ # Copyright 2016-2018 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+ require 'securerandom'
15
+
16
+ module NATS
17
+ class NUID
18
+ DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
19
+ BASE = 62
20
+ PREFIX_LENGTH = 12
21
+ SEQ_LENGTH = 10
22
+ TOTAL_LENGTH = PREFIX_LENGTH + SEQ_LENGTH
23
+ MAX_SEQ = BASE**10
24
+ MIN_INC = 33
25
+ MAX_INC = 333
26
+ INC = MAX_INC - MIN_INC
27
+
28
+ def initialize
29
+ @prand = Random.new
30
+ @seq = @prand.rand(MAX_SEQ)
31
+ @inc = MIN_INC + @prand.rand(INC)
32
+ @prefix = ''
33
+ randomize_prefix!
34
+ end
35
+
36
+ def next
37
+ @seq += @inc
38
+ if @seq >= MAX_SEQ
39
+ randomize_prefix!
40
+ reset_sequential!
41
+ end
42
+ l = @seq
43
+
44
+ # Do this inline 10 times to avoid even more extra allocs,
45
+ # then use string interpolation of everything which works
46
+ # faster for doing concat.
47
+ s_10 = DIGITS[l % BASE];
48
+
49
+ # Ugly, but parallel assignment is slightly faster here...
50
+ s_09, s_08, s_07, s_06, s_05, s_04, s_03, s_02, s_01 = \
51
+ (l /= BASE; DIGITS[l % BASE]), (l /= BASE; DIGITS[l % BASE]), (l /= BASE; DIGITS[l % BASE]),\
52
+ (l /= BASE; DIGITS[l % BASE]), (l /= BASE; DIGITS[l % BASE]), (l /= BASE; DIGITS[l % BASE]),\
53
+ (l /= BASE; DIGITS[l % BASE]), (l /= BASE; DIGITS[l % BASE]), (l /= BASE; DIGITS[l % BASE])
54
+ "#{@prefix}#{s_01}#{s_02}#{s_03}#{s_04}#{s_05}#{s_06}#{s_07}#{s_08}#{s_09}#{s_10}"
55
+ end
56
+
57
+ def randomize_prefix!
58
+ @prefix = \
59
+ SecureRandom.random_bytes(PREFIX_LENGTH).each_byte
60
+ .reduce('') do |prefix, n|
61
+ prefix << DIGITS[n % BASE]
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def reset_sequential!
68
+ @seq = @prand.rand(MAX_SEQ)
69
+ @inc = MIN_INC + @prand.rand(INC)
70
+ end
71
+
72
+ class << self
73
+ @@nuid = NUID.new.extend(MonitorMixin)
74
+ def next
75
+ @@nuid.synchronize do
76
+ @@nuid.next
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nats-pure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Waldemar Quevedo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-15 00:00:00.000000000 Z
11
+ date: 2018-04-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: NATS is an open-source, high-performance, lightweight cloud messaging
14
14
  system.
15
15
  email:
16
- - wally@apcera.com
16
+ - wally@synadia.com
17
17
  executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
@@ -21,9 +21,10 @@ files:
21
21
  - lib/nats/io/client.rb
22
22
  - lib/nats/io/parser.rb
23
23
  - lib/nats/io/version.rb
24
+ - lib/nats/nuid.rb
24
25
  homepage: https://nats.io
25
26
  licenses:
26
- - MIT
27
+ - Apache-2.0
27
28
  metadata: {}
28
29
  post_install_message:
29
30
  rdoc_options: []