nats 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![License MIT](https://img.shields.io/npm/l/express.svg)](http://opensource.org/licenses/MIT)
|
6
|
-
[![Build Status](https://travis-ci.org/nats-io/ruby-nats.svg)](http://travis-ci.org/nats-io/ruby-nats) [![Gem Version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=rb&type=5&v=0.
|
6
|
+
[![Build Status](https://travis-ci.org/nats-io/ruby-nats.svg)](http://travis-ci.org/nats-io/ruby-nats) [![Gem Version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=rb&type=5&v=0.7.0)](https://rubygems.org/gems/nats/versions/0.7.0) [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](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
|