nats-pure 0.4.0 → 0.5.0

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.
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: []