nats 0.6.0 → 0.7.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/README.md +74 -14
- data/lib/nats/client.rb +184 -38
- data/lib/nats/version.rb +1 -1
- data/nats.gemspec +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a79cc55bf741a649b4ee2ae245b57c15bbc65bd1
|
4
|
+
data.tar.gz: 2ab66dfaa047037ae06543de3e398154e0bd81f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bebf05b5735ee2c65de1ca58298ab5626f90ec31e2e743a7b90ac0d6a3243d379a04926c630aa6e8dd63ce133f5a6a1624448142ff762d5ad8e787e4afde43c
|
7
|
+
data.tar.gz: 9ab82b046d006ee3aab898577fb439568d142157ecaba641a12903fd8ed9c65022d850e10a02ebc50558486fa33a0cd1c98bfbed200a7cfc5bedee6132fe4b24
|
data/README.md
CHANGED
@@ -3,24 +3,20 @@
|
|
3
3
|
A [Ruby](http://ruby-lang.org) client for the [NATS messaging system](https://nats.io).
|
4
4
|
|
5
5
|
[](http://opensource.org/licenses/MIT)
|
6
|
-
[](http://travis-ci.org/nats-io/ruby-nats) [](http://travis-ci.org/nats-io/ruby-nats) [](https://rubygems.org/gems/nats/versions/0.7.0) [](http://www.rubydoc.info/github/nats-io/ruby-nats)
|
7
7
|
|
8
8
|
|
9
9
|
## Supported Platforms
|
10
10
|
|
11
11
|
This gem and the client are known to work on the following Ruby platforms:
|
12
12
|
|
13
|
-
- MRI 1.9, 2.0, 2.1
|
13
|
+
- MRI 1.9, 2.0, 2.1, 2.2, 2.3.0
|
14
14
|
- JRuby 1.6.8 (experimental)
|
15
15
|
|
16
|
-
Note: This installation installs a version of the NATS server written in Ruby that has been deprecated. Please utilize a supported server such as [gnatsd](https://github.com/apcera/gnatsd). nats-server will be removed in a future release.
|
17
|
-
|
18
16
|
## Getting Started
|
19
17
|
|
20
18
|
```bash
|
21
|
-
|
22
|
-
== or ==
|
23
|
-
[sudo] rake geminstall
|
19
|
+
gem install nats
|
24
20
|
|
25
21
|
nats-sub foo &
|
26
22
|
nats-pub foo 'Hello World!'
|
@@ -79,11 +75,21 @@ NATS.subscribe(subject, :queue => 'job.workers') { |msg| puts "Received '#{msg}'
|
|
79
75
|
```
|
80
76
|
|
81
77
|
## Clustered Usage
|
78
|
+
|
82
79
|
```ruby
|
83
|
-
NATS.start(:servers => ['nats://127.0.0.1:4222', 'nats://127.0.0.1:4223'] do |
|
84
|
-
puts "NATS is connected to #{
|
85
|
-
|
86
|
-
|
80
|
+
NATS.start(:servers => ['nats://127.0.0.1:4222', 'nats://127.0.0.1:4223']) do |nc|
|
81
|
+
puts "NATS is connected to #{nc.connected_server}"
|
82
|
+
|
83
|
+
nc.on_reconnect do
|
84
|
+
puts "Reconnected to server at #{nc.connected_server}"
|
85
|
+
end
|
86
|
+
|
87
|
+
nc.on_disconnect do |reason|
|
88
|
+
puts "Disconnected: #{reason}"
|
89
|
+
end
|
90
|
+
|
91
|
+
nc.on_close do
|
92
|
+
puts "Connection to NATS closed"
|
87
93
|
end
|
88
94
|
end
|
89
95
|
|
@@ -101,6 +107,7 @@ end
|
|
101
107
|
```
|
102
108
|
|
103
109
|
## Advanced Usage
|
110
|
+
|
104
111
|
```ruby
|
105
112
|
# Publish with closure, callback fires when server has processed the message
|
106
113
|
NATS.publish('foo', 'You done?') { puts 'msg processed!' }
|
@@ -117,21 +124,74 @@ NATS.unsubscribe(sid, MAX_WANTED)
|
|
117
124
|
|
118
125
|
# Multiple connections
|
119
126
|
NATS.subscribe('test') do |msg|
|
120
|
-
|
121
|
-
|
127
|
+
puts "received msg"
|
128
|
+
NATS.stop
|
122
129
|
end
|
123
130
|
|
124
131
|
# Form second connection to send message on
|
125
132
|
NATS.connect { NATS.publish('test', 'Hello World!') }
|
126
133
|
```
|
127
134
|
|
135
|
+
### TLS
|
136
|
+
|
137
|
+
Advanced customizations options for setting up a secure connection can be done by including them on connect:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
options = {
|
141
|
+
:servers => [
|
142
|
+
'nats://secret:deadbeef@127.0.0.1:4443',
|
143
|
+
'nats://secret:deadbeef@127.0.0.1:4444'
|
144
|
+
],
|
145
|
+
:max_reconnect_attempts => 10,
|
146
|
+
:reconnect_time_wait => 2,
|
147
|
+
:tls => {
|
148
|
+
:private_key_file => './spec/configs/certs/key.pem',
|
149
|
+
:cert_chain_file => './spec/configs/certs/server.pem'
|
150
|
+
# Can enable verify_peer functionality optionally by passing
|
151
|
+
# the location of a ca_file.
|
152
|
+
# :verify_peer => true,
|
153
|
+
# :ca_file => './spec/configs/certs/ca.pem'
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
# Set default callbacks
|
158
|
+
NATS.on_error do |e|
|
159
|
+
puts "Error: #{e}"
|
160
|
+
end
|
161
|
+
|
162
|
+
NATS.on_disconnect do |reason|
|
163
|
+
puts "Disconnected: #{reason}"
|
164
|
+
end
|
165
|
+
|
166
|
+
NATS.on_reconnect do |nats|
|
167
|
+
puts "Reconnected to NATS server at #{nats.connected_server}"
|
168
|
+
end
|
169
|
+
|
170
|
+
NATS.on_close do
|
171
|
+
puts "Connection to NATS closed"
|
172
|
+
EM.stop
|
173
|
+
end
|
174
|
+
|
175
|
+
NATS.start(options) do |nats|
|
176
|
+
puts "Connected to NATS at #{nats.connected_server}"
|
177
|
+
|
178
|
+
nats.subscribe("hello") do |msg|
|
179
|
+
puts "Received: #{msg}"
|
180
|
+
end
|
181
|
+
|
182
|
+
nats.flush do
|
183
|
+
nats.publish("hello", "world")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
128
188
|
See examples and benchmarks for more information..
|
129
189
|
|
130
190
|
## License
|
131
191
|
|
132
192
|
(The MIT License)
|
133
193
|
|
134
|
-
Copyright (c) 2010-
|
194
|
+
Copyright (c) 2010-2016 Derek Collison
|
135
195
|
|
136
196
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
137
197
|
of this software and associated documentation files (the "Software"), to
|
data/lib/nats/client.rb
CHANGED
@@ -58,7 +58,7 @@ module NATS
|
|
58
58
|
# When the NATS server sends us an ERROR message, this is raised/passed by default
|
59
59
|
class ServerError < Error; end #:nodoc:
|
60
60
|
|
61
|
-
# When we detect error on the client side (e.g. Fast Producer)
|
61
|
+
# When we detect error on the client side (e.g. Fast Producer, TLS required)
|
62
62
|
class ClientError < Error; end #:nodoc:
|
63
63
|
|
64
64
|
# When we cannot connect to the server (either initially or after a reconnect), this is raised/passed
|
@@ -69,8 +69,7 @@ module NATS
|
|
69
69
|
|
70
70
|
class << self
|
71
71
|
attr_reader :client, :reactor_was_running, :err_cb, :err_cb_overridden #:nodoc:
|
72
|
-
attr_reader :reconnect_cb #:nodoc
|
73
|
-
attr_accessor :timeout_cb #:nodoc
|
72
|
+
attr_reader :reconnect_cb, :close_cb, :disconnect_cb #:nodoc
|
74
73
|
|
75
74
|
alias :reactor_was_running? :reactor_was_running
|
76
75
|
|
@@ -84,6 +83,7 @@ module NATS
|
|
84
83
|
# @option opts [Boolean] :verbose Boolean that is sent to server for setting verbose protocol mode.
|
85
84
|
# @option opts [Boolean] :pedantic Boolean that is sent to server for setting pedantic mode.
|
86
85
|
# @option opts [Boolean] :ssl Boolean that is sent to server for setting TLS/SSL mode.
|
86
|
+
# @option opts [Hash] :tls Map of options for configuring secure connection handled to EM#start_tls directly.
|
87
87
|
# @option opts [Integer] :max_reconnect_attempts Integer that can be used to set the max number of reconnect tries
|
88
88
|
# @option opts [Integer] :reconnect_time_wait Integer that can be used to set the number of seconds to wait between reconnect tries
|
89
89
|
# @option opts [Integer] :ping_interval Integer that can be used to set the ping interval in seconds.
|
@@ -117,6 +117,32 @@ module NATS
|
|
117
117
|
|
118
118
|
uri = opts[:uris] || opts[:servers] || opts[:uri]
|
119
119
|
|
120
|
+
if opts[:tls]
|
121
|
+
case
|
122
|
+
when opts[:tls][:ca_file]
|
123
|
+
# Ensure that the file exists before going further
|
124
|
+
# in order to report configuration errors during
|
125
|
+
# connect synchronously.
|
126
|
+
if !File.readable?(opts[:tls][:ca_file])
|
127
|
+
raise(Error, "TLS Verification is enabled but ca_file %s is not readable" % opts[:tls][:ca_file])
|
128
|
+
end
|
129
|
+
|
130
|
+
# Certificate is supplied so assume we mean verification by default,
|
131
|
+
# but still allow disabling explicitly by setting to false.
|
132
|
+
opts[:tls][:verify_peer] ||= true
|
133
|
+
when (opts[:tls][:verify_peer] && !opts[:tls][:ca_file])
|
134
|
+
raise(Error, "TLS Verification is enabled but ca_file is not set")
|
135
|
+
else
|
136
|
+
# Otherwise, disable verifying peer by default,
|
137
|
+
# thus never reaching EM#ssl_verify_peer
|
138
|
+
opts[:tls][:verify_peer] = false
|
139
|
+
end
|
140
|
+
|
141
|
+
# Allow overriding directly but default to those which server supports.
|
142
|
+
opts[:tls][:ssl_version] ||= %w(tlsv1 tlsv1_1 tlsv1_2)
|
143
|
+
opts[:tls][:protocols] ||= %w(tlsv1 tlsv1_1 tlsv1_2)
|
144
|
+
end
|
145
|
+
|
120
146
|
# If they pass an array here just pass along to the real connection, and use first as the first attempt..
|
121
147
|
# Real connection will do proper walk throughs etc..
|
122
148
|
unless uri.nil?
|
@@ -127,6 +153,8 @@ module NATS
|
|
127
153
|
end
|
128
154
|
|
129
155
|
@err_cb = proc { |e| raise e } unless err_cb
|
156
|
+
@close_cb = proc { } unless close_cb
|
157
|
+
@disconnect_cb = proc { } unless disconnect_cb
|
130
158
|
|
131
159
|
client = EM.connect(@uri.host, @uri.port, self, opts)
|
132
160
|
client.on_connect(&blk) if blk
|
@@ -157,6 +185,9 @@ module NATS
|
|
157
185
|
client.close if (client and (client.connected? || client.reconnecting?))
|
158
186
|
blk.call if blk
|
159
187
|
@err_cb = nil
|
188
|
+
@close_cb = nil
|
189
|
+
@reconnect_cb = nil
|
190
|
+
@disconnect_cb = nil
|
160
191
|
end
|
161
192
|
|
162
193
|
# @return [URI] Connected server
|
@@ -202,6 +233,20 @@ module NATS
|
|
202
233
|
@client.on_reconnect(&callback) unless @client.nil?
|
203
234
|
end
|
204
235
|
|
236
|
+
# Set the default on_disconnect callback.
|
237
|
+
# @param [Block] &callback called whenever client disconnects from a server.
|
238
|
+
def on_disconnect(&callback)
|
239
|
+
@disconnect_cb = callback
|
240
|
+
@client.on_disconnect(&callback) unless @client.nil?
|
241
|
+
end
|
242
|
+
|
243
|
+
# Set the default on_closed callback.
|
244
|
+
# @param [Block] &callback called when will reach a state when will no longer be connected.
|
245
|
+
def on_close(&callback)
|
246
|
+
@close_cb = callback
|
247
|
+
@client.on_close(&callback) unless @client.nil?
|
248
|
+
end
|
249
|
+
|
205
250
|
# Publish a message using the default client connection.
|
206
251
|
# @see NATS#publish
|
207
252
|
def publish(*args, &blk)
|
@@ -282,6 +327,7 @@ module NATS
|
|
282
327
|
attr_reader :connected, :connect_cb, :err_cb, :err_cb_overridden, :pongs_received #:nodoc:
|
283
328
|
attr_reader :closing, :reconnecting, :server_pool, :options, :server_info #:nodoc
|
284
329
|
attr_reader :msgs_received, :msgs_sent, :bytes_received, :bytes_sent, :pings
|
330
|
+
attr_reader :disconnect_cb, :close_cb
|
285
331
|
|
286
332
|
alias :connected? :connected
|
287
333
|
alias :closing? :closing
|
@@ -290,16 +336,26 @@ module NATS
|
|
290
336
|
def initialize(options)
|
291
337
|
@options = options
|
292
338
|
process_uri_options
|
293
|
-
|
294
|
-
@ssl = options[:ssl] if options[:ssl]
|
339
|
+
|
295
340
|
@buf = nil
|
296
341
|
@ssid, @subs = 1, {}
|
297
342
|
@err_cb = NATS.err_cb
|
298
|
-
@
|
343
|
+
@close_cb = NATS.close_cb
|
299
344
|
@reconnect_cb = NATS.reconnect_cb
|
345
|
+
@disconnect_cb = NATS.disconnect_cb
|
346
|
+
@reconnect_timer, @needed = nil, nil
|
300
347
|
@connected, @closing, @reconnecting, @conn_cb_called = false, false, false, false
|
301
348
|
@msgs_received = @msgs_sent = @bytes_received = @bytes_sent = @pings = 0
|
302
349
|
@pending_size = 0
|
350
|
+
@server_info = { }
|
351
|
+
|
352
|
+
# Mark whether we should be connecting securely, try best effort
|
353
|
+
# in being compatible with present ssl support.
|
354
|
+
@ssl = false
|
355
|
+
@tls = nil
|
356
|
+
@tls = options[:tls] if options[:tls]
|
357
|
+
@ssl = options[:ssl] if options[:ssl] or @tls
|
358
|
+
|
303
359
|
send_connect_command
|
304
360
|
end
|
305
361
|
|
@@ -411,17 +467,29 @@ module NATS
|
|
411
467
|
end
|
412
468
|
|
413
469
|
# Define a callback to be called when errors occur on the client connection.
|
414
|
-
# @param [Block] &
|
470
|
+
# @param [Block] &callback called when an error has been detected.
|
415
471
|
def on_error(&callback)
|
416
472
|
@err_cb, @err_cb_overridden = callback, true
|
417
473
|
end
|
418
474
|
|
419
475
|
# Define a callback to be called when a reconnect attempt is made.
|
420
|
-
# @param [Block] &
|
476
|
+
# @param [Block] &callback called when a reconnect attempt is made.
|
421
477
|
def on_reconnect(&callback)
|
422
478
|
@reconnect_cb = callback
|
423
479
|
end
|
424
480
|
|
481
|
+
# Define a callback to be called when client is disconnected from server.
|
482
|
+
# @param [Block] &callback called whenever client disconnects from a server.
|
483
|
+
def on_disconnect(&callback)
|
484
|
+
@disconnect_cb = callback
|
485
|
+
end
|
486
|
+
|
487
|
+
# Define a callback to be called when client is disconnected from server.
|
488
|
+
# @param [Block] &callback called when will reach a state when will no longer be connected.
|
489
|
+
def on_close(&callback)
|
490
|
+
@close_cb = callback
|
491
|
+
end
|
492
|
+
|
425
493
|
# Close the connection to the server.
|
426
494
|
def close
|
427
495
|
@closing = true
|
@@ -448,7 +516,7 @@ module NATS
|
|
448
516
|
cs = {
|
449
517
|
:verbose => @options[:verbose],
|
450
518
|
:pedantic => @options[:pedantic],
|
451
|
-
:lang =>
|
519
|
+
:lang => :ruby,
|
452
520
|
:version => VERSION
|
453
521
|
}
|
454
522
|
if auth_connection?
|
@@ -456,6 +524,8 @@ module NATS
|
|
456
524
|
cs[:pass] = @uri.password
|
457
525
|
end
|
458
526
|
cs[:ssl_required] = @ssl if @ssl
|
527
|
+
cs[:tls_required] = true if @tls
|
528
|
+
|
459
529
|
"CONNECT #{cs.to_json}#{CR_LF}"
|
460
530
|
end
|
461
531
|
|
@@ -567,27 +637,55 @@ module NATS
|
|
567
637
|
# parser gets what it needs. For the json gem :symbolize_name, for yajl
|
568
638
|
# :symbolize_keys, and for oj :symbol_keys.
|
569
639
|
@server_info = JSON.parse(info, :symbolize_keys => true, :symbolize_names => true, :symbol_keys => true)
|
570
|
-
|
571
|
-
|
640
|
+
|
641
|
+
case
|
642
|
+
when (server_using_secure_connection? and client_using_secure_connection?)
|
643
|
+
# Allow parameterizing secure connection via EM#start_tls directly if present.
|
644
|
+
start_tls(@tls || {})
|
645
|
+
when (server_using_secure_connection? and !client_using_secure_connection?)
|
646
|
+
# Call unbind since there is a configuration mismatch between client/server
|
647
|
+
# anyway and communication cannot happen in this state.
|
648
|
+
err_cb.call(NATS::ClientError.new('TLS/SSL required by server'))
|
649
|
+
close_connection_after_writing
|
650
|
+
when (client_using_secure_connection? and !server_using_secure_connection?)
|
651
|
+
err_cb.call(NATS::ClientError.new('TLS/SSL not supported by server'))
|
652
|
+
close_connection_after_writing
|
572
653
|
else
|
573
|
-
|
574
|
-
err_cb.call(NATS::ClientError.new('TLS/SSL required by server'))
|
575
|
-
elsif @ssl
|
576
|
-
err_cb.call(NATS::ClientError.new('TLS/SSL not supported by server'))
|
577
|
-
end
|
654
|
+
# Otherwise, use a regular connection.
|
578
655
|
end
|
656
|
+
|
579
657
|
if @server_info[:auth_required]
|
580
658
|
current = server_pool.first
|
581
659
|
current[:auth_required] = true
|
660
|
+
# Send pending connect followed by ping/pong to ensure we're authorized.
|
582
661
|
queue_server_rt { current[:auth_ok] = true }
|
583
662
|
flush_pending
|
584
663
|
end
|
664
|
+
|
585
665
|
@server_info
|
586
666
|
end
|
587
667
|
|
588
|
-
def
|
589
|
-
@
|
590
|
-
|
668
|
+
def client_using_secure_connection?
|
669
|
+
@tls || @ssl
|
670
|
+
end
|
671
|
+
|
672
|
+
def server_using_secure_connection?
|
673
|
+
@server_info[:ssl_required] || @server_info[:tls_required]
|
674
|
+
end
|
675
|
+
|
676
|
+
def ssl_verify_peer(cert)
|
677
|
+
ca_file = File.read(@options[:tls][:ca_file])
|
678
|
+
ca = OpenSSL::X509::Certificate.new(ca_file)
|
679
|
+
incoming = OpenSSL::X509::Certificate.new(cert)
|
680
|
+
|
681
|
+
unless incoming.issuer.to_s == ca.subject.to_s && incoming.verify(ca.public_key)
|
682
|
+
err_cb.call(NATS::ConnectError.new("TLS Verification failed checking issuer based on CA %s" % @options[:ca_file]))
|
683
|
+
false
|
684
|
+
else
|
685
|
+
true
|
686
|
+
end
|
687
|
+
rescue NATS::ConnectError
|
688
|
+
false
|
591
689
|
end
|
592
690
|
|
593
691
|
def cancel_ping_timer
|
@@ -598,23 +696,43 @@ module NATS
|
|
598
696
|
end
|
599
697
|
|
600
698
|
def connection_completed #:nodoc:
|
601
|
-
@
|
699
|
+
@parse_state = AWAITING_CONTROL_LINE
|
700
|
+
|
701
|
+
# Delay sending CONNECT or any other command here until we are sure
|
702
|
+
# that we have a valid established secure connection.
|
703
|
+
return if (@ssl or @tls)
|
704
|
+
|
705
|
+
# Mark that we established already TCP connection to the server. In case of TLS,
|
706
|
+
# prepare commands which will be dispatched to server and delay flushing until
|
707
|
+
# we have processed the INFO line sent by the server and done the handshake.
|
708
|
+
@connected = true
|
709
|
+
process_connect
|
710
|
+
end
|
711
|
+
|
712
|
+
def ssl_handshake_completed
|
713
|
+
@connected = true
|
714
|
+
process_connect
|
715
|
+
end
|
602
716
|
|
717
|
+
def process_connect #:nodoc:
|
718
|
+
# Reset reconnect attempts since TCP connection has been successful at this point.
|
603
719
|
current = server_pool.first
|
604
720
|
current[:was_connected] = true
|
605
|
-
current[:reconnect_attempts]
|
721
|
+
current[:reconnect_attempts] ||= 0
|
606
722
|
cancel_reconnect_timer if reconnecting?
|
607
723
|
|
608
|
-
#
|
724
|
+
# Whip through any pending SUB commands since we replay
|
609
725
|
# all subscriptions already done anyway.
|
610
|
-
@pending.delete_if { |sub| sub[0..2] == SUB_OP }
|
726
|
+
@pending.delete_if { |sub| sub[0..2] == SUB_OP } if @pending
|
611
727
|
@subs.each_pair { |k, v| send_command("SUB #{v[:subject]} #{v[:queue]} #{k}#{CR_LF}") }
|
612
728
|
|
613
729
|
unless user_err_cb? or reconnecting?
|
614
730
|
@err_cb = proc { |e| raise e }
|
615
731
|
end
|
616
732
|
|
617
|
-
|
733
|
+
# We have validated the connection at this point so send CONNECT
|
734
|
+
# and any other pending commands which we need to the server.
|
735
|
+
flush_pending
|
618
736
|
|
619
737
|
if (connect_cb and not @conn_cb_called)
|
620
738
|
# We will round trip the server here to make sure all state from any pending commands
|
@@ -625,17 +743,18 @@ module NATS
|
|
625
743
|
end
|
626
744
|
end
|
627
745
|
|
746
|
+
# Notify via reconnect callback that we are again plugged again into the system.
|
628
747
|
if reconnecting?
|
629
748
|
@reconnecting = false
|
630
|
-
@reconnect_cb.call unless @reconnect_cb.nil?
|
749
|
+
@reconnect_cb.call(self) unless @reconnect_cb.nil?
|
631
750
|
end
|
632
751
|
|
633
|
-
@parse_state = AWAITING_CONTROL_LINE
|
634
|
-
|
635
752
|
# Initialize ping timer and processing
|
636
753
|
@pings_outstanding = 0
|
637
754
|
@pongs_received = 0
|
638
|
-
@ping_timer = EM.add_periodic_timer(@options[:ping_interval])
|
755
|
+
@ping_timer = EM.add_periodic_timer(@options[:ping_interval]) do
|
756
|
+
send_ping
|
757
|
+
end
|
639
758
|
end
|
640
759
|
|
641
760
|
def send_ping #:nodoc:
|
@@ -656,7 +775,7 @@ module NATS
|
|
656
775
|
end
|
657
776
|
|
658
777
|
def should_delay_connect?(server)
|
659
|
-
server[:was_connected] && server[:reconnect_attempts] >=
|
778
|
+
server[:was_connected] && server[:reconnect_attempts] >= 0
|
660
779
|
end
|
661
780
|
|
662
781
|
def schedule_reconnect #:nodoc:
|
@@ -666,9 +785,14 @@ module NATS
|
|
666
785
|
end
|
667
786
|
|
668
787
|
def unbind #:nodoc:
|
788
|
+
# Allow notifying from which server we were disconnected,
|
789
|
+
# but only when we didn't trigger disconnecting ourselves.
|
790
|
+
if @disconnect_cb and connected? and not closing?
|
791
|
+
disconnect_cb.call(NATS::ConnectError.new(disconnect_error_string))
|
792
|
+
end
|
793
|
+
|
669
794
|
# If we are closing or shouldn't reconnect, go ahead and disconnect.
|
670
795
|
process_disconnect and return if (closing? or should_not_reconnect?)
|
671
|
-
|
672
796
|
@reconnecting = true if connected?
|
673
797
|
@connected = false
|
674
798
|
@pending = @pongs = nil
|
@@ -698,12 +822,18 @@ module NATS
|
|
698
822
|
end
|
699
823
|
|
700
824
|
def disconnect_error_string
|
701
|
-
return "Client disconnected from server on #{@uri}
|
825
|
+
return "Client disconnected from server on #{@uri}" if @connected
|
702
826
|
return "Could not connect to server on #{@uri}"
|
703
827
|
end
|
704
828
|
|
705
829
|
def process_disconnect #:nodoc:
|
706
|
-
|
830
|
+
# Mute error callback when user has called NATS.close on purpose.
|
831
|
+
if not closing? and @err_cb
|
832
|
+
# Always call error callback for compatibility with previous behavior.
|
833
|
+
err_cb.call(NATS::ConnectError.new(disconnect_error_string))
|
834
|
+
end
|
835
|
+
close_cb.call if @close_cb
|
836
|
+
|
707
837
|
true # Chaining
|
708
838
|
ensure
|
709
839
|
cancel_ping_timer
|
@@ -716,13 +846,17 @@ module NATS
|
|
716
846
|
end
|
717
847
|
|
718
848
|
def can_reuse_server?(server) #:nodoc:
|
719
|
-
|
849
|
+
# If we will retry a number of times to reconnect to a server
|
850
|
+
# unless we got an error from it already.
|
851
|
+
reconnecting? && server[:reconnect_attempts] <= @options[:max_reconnect_attempts] && !server[:error_received]
|
720
852
|
end
|
721
853
|
|
722
854
|
def attempt_reconnect #:nodoc:
|
723
855
|
@reconnect_timer = nil
|
724
856
|
current = server_pool.first
|
725
|
-
current[:reconnect_attempts]
|
857
|
+
current[:reconnect_attempts] ||= 0
|
858
|
+
current[:reconnect_attempts] += 1
|
859
|
+
|
726
860
|
send_connect_command
|
727
861
|
begin
|
728
862
|
EM.reconnect(@uri.host, @uri.port, self)
|
@@ -734,11 +868,15 @@ module NATS
|
|
734
868
|
end
|
735
869
|
|
736
870
|
def send_command(command, priority = false) #:nodoc:
|
737
|
-
|
871
|
+
needs_flush = (connected? && @pending.nil?)
|
872
|
+
|
738
873
|
@pending ||= []
|
739
874
|
@pending << command unless priority
|
740
875
|
@pending.unshift(command) if priority
|
741
876
|
@pending_size += command.bytesize
|
877
|
+
|
878
|
+
EM.next_tick { flush_pending } if needs_flush
|
879
|
+
|
742
880
|
flush_pending if (connected? && @pending_size > MAX_PENDING_SIZE)
|
743
881
|
if (@options[:fast_producer_error] && pending_data_size > FAST_PRODUCER_THRESHOLD)
|
744
882
|
err_cb.call(NATS::ClientError.new("Fast Producer: #{pending_data_size} bytes outstanding"))
|
@@ -773,12 +911,20 @@ module NATS
|
|
773
911
|
def schedule_primary_and_connect #:nodoc:
|
774
912
|
# Dump the one we were trying if it wasn't connected
|
775
913
|
current = server_pool.shift
|
776
|
-
|
777
|
-
|
778
|
-
#
|
914
|
+
|
915
|
+
# In case there was an error from the server we will take it out from rotation
|
916
|
+
# unless we specify infinite reconnects via setting :max_reconnect_attempts to -1
|
917
|
+
if current && (options[:max_reconnect_attempts] < 0 || can_reuse_server?(current))
|
918
|
+
server_pool << current
|
919
|
+
end
|
920
|
+
|
921
|
+
# If we are out of options, go ahead and disconnect then
|
922
|
+
# handle closing connection to NATS.
|
779
923
|
process_disconnect and return if server_pool.empty?
|
924
|
+
|
780
925
|
# bind new one
|
781
926
|
next_server = bind_primary
|
927
|
+
|
782
928
|
# If the next one was connected and we are trying to reconnect
|
783
929
|
# set up timer if we tried once already.
|
784
930
|
if should_delay_connect?(next_server)
|
data/lib/nats/version.rb
CHANGED
data/nats.gemspec
CHANGED
@@ -17,7 +17,7 @@ spec = Gem::Specification.new do |s|
|
|
17
17
|
s.authors = ['Derek Collison']
|
18
18
|
s.email = ['derek.collison@gmail.com']
|
19
19
|
|
20
|
-
s.add_dependency('eventmachine', '~> 1.
|
20
|
+
s.add_dependency('eventmachine', '~> 1.2', '>= 1.2.0')
|
21
21
|
s.add_dependency('json_pure', '~> 1.8', '>= 1.8.1')
|
22
22
|
s.add_dependency('daemons', '~> 1.1', '>= 1.2.2')
|
23
23
|
s.add_dependency('thin', '~> 1.6', '>= 1.6.3')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Derek Collison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
20
|
-
- -
|
19
|
+
version: '1.2'
|
20
|
+
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.0
|
22
|
+
version: 1.2.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '1.
|
30
|
-
- -
|
29
|
+
version: '1.2'
|
30
|
+
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 1.0
|
32
|
+
version: 1.2.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: json_pure
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|