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 +4 -4
- data/lib/nats/io/client.rb +120 -4
- data/lib/nats/io/parser.rb +14 -0
- data/lib/nats/io/version.rb +15 -1
- data/lib/nats/nuid.rb +81 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 741d87f63f2851dc25639453f9cd5ed68b3e2bfb66f45f1b5fe6caa9b3e352dd
|
4
|
+
data.tar.gz: 1af44d28a31788e37fbb50d14f966ff30805ee42614ae37a7ab3599edd0de4f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 432d3b3cf28752ec19c6278763ec5e1ef5992ee9d57796aeadb41b978028b3700c699795134f46297c982d9fc98fc3979d0760842f74fb528977e62b66431c9c
|
7
|
+
data.tar.gz: 758a3b3deb4c2b14198bca42b647d2b11726c08d7150a914a8835a64fa6720d57d28c2207ddcd6ad40995427902ab1afd6705f2ab4c4ea1adbe9e131ccc1ea32
|
data/lib/nats/io/client.rb
CHANGED
@@ -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
|
348
|
-
#
|
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.
|
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
|
|
data/lib/nats/io/parser.rb
CHANGED
@@ -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
|
|
data/lib/nats/io/version.rb
CHANGED
@@ -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.
|
18
|
+
VERSION = "0.5.0"
|
5
19
|
LANG = "#{RUBY_ENGINE}2".freeze
|
6
20
|
PROTOCOL = 1
|
7
21
|
end
|
data/lib/nats/nuid.rb
ADDED
@@ -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
|
+
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-
|
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@
|
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
|
-
-
|
27
|
+
- Apache-2.0
|
27
28
|
metadata: {}
|
28
29
|
post_install_message:
|
29
30
|
rdoc_options: []
|