nats-pure 0.1.2 → 0.2.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 +95 -61
- data/lib/nats/io/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a1804a68dcb41e7e76ca9f53fc6b13fc44605090
|
|
4
|
+
data.tar.gz: c2b611901423068cdcd6e6add32b18b9079e47fd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7dbaaa96f906080b70992031edbe1d257fe5248f9ff72be6df19050b4554cacce53382946196395d24cae27a3db15de4d4acf07c67097c45d76883423f092419
|
|
7
|
+
data.tar.gz: e4dcd3d62141d47273518fc0252755495162cd0a4d49432647838a06d65203ee4bbbbabe026217567a253ba4da531d293a5e29f6c321e97548419433d1529602
|
data/lib/nats/io/client.rb
CHANGED
|
@@ -75,6 +75,9 @@ module NATS
|
|
|
75
75
|
# When we do not get a result within a specified time.
|
|
76
76
|
class Timeout < Error; end
|
|
77
77
|
|
|
78
|
+
# When there is an i/o timeout with the socket.
|
|
79
|
+
class SocketTimeoutError < Error; end
|
|
80
|
+
|
|
78
81
|
# When we use an invalid subject.
|
|
79
82
|
class BadSubject < Error; end
|
|
80
83
|
|
|
@@ -162,6 +165,7 @@ module NATS
|
|
|
162
165
|
opts[:max_reconnect_attempts] = ENV['NATS_MAX_RECONNECT_ATTEMPTS'].to_i unless ENV['NATS_MAX_RECONNECT_ATTEMPTS'].nil?
|
|
163
166
|
opts[:ping_interval] = ENV['NATS_PING_INTERVAL'].to_i unless ENV['NATS_PING_INTERVAL'].nil?
|
|
164
167
|
opts[:max_outstanding_pings] = ENV['NATS_MAX_OUTSTANDING_PINGS'].to_i unless ENV['NATS_MAX_OUTSTANDING_PINGS'].nil?
|
|
168
|
+
opts[:connect_timeout] ||= DEFAULT_CONNECT_TIMEOUT
|
|
165
169
|
@options = opts
|
|
166
170
|
|
|
167
171
|
# Process servers in the NATS cluster and pick one to connect
|
|
@@ -195,7 +199,7 @@ module NATS
|
|
|
195
199
|
current[:reconnect_attempts] = 0
|
|
196
200
|
rescue NoServersError => e
|
|
197
201
|
@disconnect_cb.call(e) if @disconnect_cb
|
|
198
|
-
raise e
|
|
202
|
+
raise @last_err || e
|
|
199
203
|
rescue => e
|
|
200
204
|
# Capture sticky error
|
|
201
205
|
synchronize { @last_err = e }
|
|
@@ -207,6 +211,10 @@ module NATS
|
|
|
207
211
|
raise e
|
|
208
212
|
end
|
|
209
213
|
|
|
214
|
+
# Clean up any connecting state and close connection without
|
|
215
|
+
# triggering the disconnection/closed callbacks.
|
|
216
|
+
close_connection(DISCONNECTED, false)
|
|
217
|
+
|
|
210
218
|
# always sleep here to safe guard against errors before current[:was_connected]
|
|
211
219
|
# is set for the first time
|
|
212
220
|
sleep @options[:reconnect_time_wait] if @options[:reconnect_time_wait]
|
|
@@ -395,7 +403,8 @@ module NATS
|
|
|
395
403
|
@last_err = NATS::IO::ServerError.new(err)
|
|
396
404
|
end
|
|
397
405
|
|
|
398
|
-
|
|
406
|
+
# Process disconnect under a different thread as reading loop
|
|
407
|
+
Thread.new { close }
|
|
399
408
|
end
|
|
400
409
|
|
|
401
410
|
def process_msg(subject, sid, reply, data)
|
|
@@ -451,54 +460,7 @@ module NATS
|
|
|
451
460
|
# and there are any pending messages, should not be used while
|
|
452
461
|
# holding the lock.
|
|
453
462
|
def close
|
|
454
|
-
|
|
455
|
-
return if @status == CLOSED
|
|
456
|
-
@status = CLOSED
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
# Kick the flusher so it bails due to closed state
|
|
460
|
-
@flush_queue << :fallout
|
|
461
|
-
Thread.pass
|
|
462
|
-
|
|
463
|
-
# FIXME: More graceful way of handling the following?
|
|
464
|
-
# Ensure ping interval and flusher are not running anymore
|
|
465
|
-
@ping_interval_thread.exit if @ping_interval_thread.alive?
|
|
466
|
-
@flusher_thread.exit if @flusher_thread.alive?
|
|
467
|
-
@read_loop_thread.exit if @read_loop_thread.alive?
|
|
468
|
-
|
|
469
|
-
# TODO: Delete any other state which we are not using here too.
|
|
470
|
-
synchronize do
|
|
471
|
-
@pongs.synchronize do
|
|
472
|
-
@pongs.each do |pong|
|
|
473
|
-
pong.signal
|
|
474
|
-
end
|
|
475
|
-
@pongs.clear
|
|
476
|
-
end
|
|
477
|
-
|
|
478
|
-
# Try to write any pending flushes in case
|
|
479
|
-
# we have a connection then close it.
|
|
480
|
-
begin
|
|
481
|
-
cmds = []
|
|
482
|
-
cmds << @pending_queue.pop until @pending_queue.empty?
|
|
483
|
-
|
|
484
|
-
# FIXME: Fails when empty on TLS connection?
|
|
485
|
-
@io.write(cmds.join) unless cmds.empty?
|
|
486
|
-
rescue => e
|
|
487
|
-
@last_err = e
|
|
488
|
-
@err_cb.call(e) if @err_cb
|
|
489
|
-
end if @io and not @io.closed?
|
|
490
|
-
|
|
491
|
-
# TODO: Destroy any remaining subscriptions
|
|
492
|
-
@disconnect_cb.call if @disconnect_cb
|
|
493
|
-
@close_cb.call if @close_cb
|
|
494
|
-
|
|
495
|
-
# Close the established connection in case
|
|
496
|
-
# we still have it.
|
|
497
|
-
if @io
|
|
498
|
-
@io.close
|
|
499
|
-
@io = nil
|
|
500
|
-
end
|
|
501
|
-
end
|
|
463
|
+
close_connection(CLOSED, true)
|
|
502
464
|
end
|
|
503
465
|
|
|
504
466
|
def new_inbox
|
|
@@ -678,6 +640,8 @@ module NATS
|
|
|
678
640
|
return if should_bail
|
|
679
641
|
|
|
680
642
|
synchronize do
|
|
643
|
+
@last_err = e
|
|
644
|
+
|
|
681
645
|
# If we were connected and configured to reconnect,
|
|
682
646
|
# then trigger disconnect and start reconnection logic
|
|
683
647
|
if connected? and should_reconnect?
|
|
@@ -710,7 +674,6 @@ module NATS
|
|
|
710
674
|
|
|
711
675
|
# Otherwise, stop trying to reconnect and close the connection
|
|
712
676
|
@status = DISCONNECTED
|
|
713
|
-
@last_err = e
|
|
714
677
|
end
|
|
715
678
|
|
|
716
679
|
# Otherwise close the connection to NATS
|
|
@@ -799,7 +762,7 @@ module NATS
|
|
|
799
762
|
end
|
|
800
763
|
|
|
801
764
|
def process_connect_init
|
|
802
|
-
line = @io.read_line
|
|
765
|
+
line = @io.read_line(options[:connect_timeout])
|
|
803
766
|
_, info_json = line.split(' ')
|
|
804
767
|
process_info(info_json)
|
|
805
768
|
|
|
@@ -840,11 +803,11 @@ module NATS
|
|
|
840
803
|
# Send ping/pong after connect
|
|
841
804
|
@io.write(PING_REQUEST)
|
|
842
805
|
|
|
843
|
-
next_op = @io.read_line
|
|
806
|
+
next_op = @io.read_line(options[:connect_timeout])
|
|
844
807
|
if @options[:verbose]
|
|
845
808
|
# Need to get another command here if verbose
|
|
846
809
|
raise NATS::IO::ConnectError.new("expected to receive +OK") unless next_op =~ NATS::Protocol::OK
|
|
847
|
-
next_op = @io.read_line
|
|
810
|
+
next_op = @io.read_line(options[:connect_timeout])
|
|
848
811
|
end
|
|
849
812
|
|
|
850
813
|
case next_op
|
|
@@ -920,6 +883,72 @@ module NATS
|
|
|
920
883
|
@reconnect_cb.call if @reconnect_cb
|
|
921
884
|
end
|
|
922
885
|
|
|
886
|
+
def close_connection(conn_status, do_cbs=true)
|
|
887
|
+
synchronize do
|
|
888
|
+
if @status == CLOSED
|
|
889
|
+
@status = conn_status
|
|
890
|
+
return
|
|
891
|
+
end
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
# Kick the flusher so it bails due to closed state
|
|
895
|
+
@flush_queue << :fallout if @flush_queue
|
|
896
|
+
Thread.pass
|
|
897
|
+
|
|
898
|
+
# FIXME: More graceful way of handling the following?
|
|
899
|
+
# Ensure ping interval and flusher are not running anymore
|
|
900
|
+
if @ping_interval_thread and @ping_interval_thread.alive?
|
|
901
|
+
@ping_interval_thread.exit
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
if @flusher_thread and @flusher_thread.alive?
|
|
905
|
+
@flusher_thread.exit
|
|
906
|
+
end
|
|
907
|
+
|
|
908
|
+
if @read_loop_thread and @read_loop_thread.alive?
|
|
909
|
+
@read_loop_thread.exit
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
# TODO: Delete any other state which we are not using here too.
|
|
913
|
+
synchronize do
|
|
914
|
+
@pongs.synchronize do
|
|
915
|
+
@pongs.each do |pong|
|
|
916
|
+
pong.signal
|
|
917
|
+
end
|
|
918
|
+
@pongs.clear
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
# Try to write any pending flushes in case
|
|
922
|
+
# we have a connection then close it.
|
|
923
|
+
should_flush = (@pending_queue && @io && @io.socket && !@io.closed?)
|
|
924
|
+
begin
|
|
925
|
+
cmds = []
|
|
926
|
+
cmds << @pending_queue.pop until @pending_queue.empty?
|
|
927
|
+
|
|
928
|
+
# FIXME: Fails when empty on TLS connection?
|
|
929
|
+
@io.write(cmds.join) unless cmds.empty?
|
|
930
|
+
rescue => e
|
|
931
|
+
@last_err = e
|
|
932
|
+
@err_cb.call(e) if @err_cb
|
|
933
|
+
end if should_flush
|
|
934
|
+
|
|
935
|
+
# TODO: Destroy any remaining subscriptions
|
|
936
|
+
if do_cbs
|
|
937
|
+
@disconnect_cb.call(@last_err) if @disconnect_cb
|
|
938
|
+
@close_cb.call if @close_cb
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
@status = conn_status
|
|
942
|
+
|
|
943
|
+
# Close the established connection in case
|
|
944
|
+
# we still have it.
|
|
945
|
+
if @io
|
|
946
|
+
@io.close if @io.socket
|
|
947
|
+
@io = nil
|
|
948
|
+
end
|
|
949
|
+
end
|
|
950
|
+
end
|
|
951
|
+
|
|
923
952
|
def start_threads!
|
|
924
953
|
# Reading loop for gathering data
|
|
925
954
|
@read_loop_thread = Thread.new { read_loop }
|
|
@@ -994,24 +1023,27 @@ module NATS
|
|
|
994
1023
|
|
|
995
1024
|
def read_line(deadline=nil)
|
|
996
1025
|
# FIXME: Should accumulate and read in a non blocking way instead
|
|
997
|
-
|
|
1026
|
+
unless ::IO.select([@socket], nil, nil, deadline)
|
|
1027
|
+
raise SocketTimeoutError
|
|
1028
|
+
end
|
|
998
1029
|
@socket.gets
|
|
999
1030
|
end
|
|
1000
1031
|
|
|
1001
1032
|
def read(max_bytes, deadline=nil)
|
|
1033
|
+
|
|
1002
1034
|
begin
|
|
1003
1035
|
return @socket.read_nonblock(max_bytes)
|
|
1004
1036
|
rescue *NBIO_READ_EXCEPTIONS
|
|
1005
1037
|
if ::IO.select([@socket], nil, nil, deadline)
|
|
1006
1038
|
retry
|
|
1007
1039
|
else
|
|
1008
|
-
raise
|
|
1040
|
+
raise SocketTimeoutError
|
|
1009
1041
|
end
|
|
1010
1042
|
rescue *NBIO_WRITE_EXCEPTIONS
|
|
1011
1043
|
if ::IO.select(nil, [@socket], nil, deadline)
|
|
1012
1044
|
retry
|
|
1013
1045
|
else
|
|
1014
|
-
raise
|
|
1046
|
+
raise SocketTimeoutError
|
|
1015
1047
|
end
|
|
1016
1048
|
end
|
|
1017
1049
|
rescue EOFError => e
|
|
@@ -1039,13 +1071,13 @@ module NATS
|
|
|
1039
1071
|
if ::IO.select(nil, [@socket], nil, deadline)
|
|
1040
1072
|
retry
|
|
1041
1073
|
else
|
|
1042
|
-
raise
|
|
1074
|
+
raise SocketTimeoutError
|
|
1043
1075
|
end
|
|
1044
1076
|
rescue *NBIO_READ_EXCEPTIONS => e
|
|
1045
1077
|
if ::IO.select([@socket], nil, nil, deadline)
|
|
1046
1078
|
retry
|
|
1047
1079
|
else
|
|
1048
|
-
raise
|
|
1080
|
+
raise SocketTimeoutError
|
|
1049
1081
|
end
|
|
1050
1082
|
end
|
|
1051
1083
|
end
|
|
@@ -1070,8 +1102,10 @@ module NATS
|
|
|
1070
1102
|
|
|
1071
1103
|
begin
|
|
1072
1104
|
sock.connect_nonblock(sockaddr)
|
|
1073
|
-
rescue Errno::EINPROGRESS
|
|
1074
|
-
|
|
1105
|
+
rescue Errno::EINPROGRESS, Errno::EALREADY, ::IO::WaitWritable
|
|
1106
|
+
unless ::IO.select(nil, [sock], nil, @connect_timeout)
|
|
1107
|
+
raise SocketTimeoutError
|
|
1108
|
+
end
|
|
1075
1109
|
|
|
1076
1110
|
# Confirm that connection was established
|
|
1077
1111
|
begin
|
data/lib/nats/io/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nats-pure
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.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: 2016-12-
|
|
11
|
+
date: 2016-12-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: NATS is an open-source, high-performance, lightweight cloud messaging
|
|
14
14
|
system.
|
|
@@ -41,7 +41,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
41
41
|
version: '0'
|
|
42
42
|
requirements: []
|
|
43
43
|
rubyforge_project:
|
|
44
|
-
rubygems_version: 2.
|
|
44
|
+
rubygems_version: 2.6.8
|
|
45
45
|
signing_key:
|
|
46
46
|
specification_version: 4
|
|
47
47
|
summary: NATS is an open-source, high-performance, lightweight cloud messaging system.
|