nats-pure 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|