nats-streaming 0.1.0 → 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/stan/client.rb +82 -20
- data/lib/stan/version.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b75b9c85c86a9586a19f5b9a7b742f69f4b230df
|
4
|
+
data.tar.gz: fac785865b216da75a7e1255e6b20dd33bb1a7da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b1738c21713867a7f3d14405620539fb6e8cdc6306665bd2cdce3a6e6c9e19e46a0c4037c1408e1d09fc63d95914cdea78ec0b727ab18be405ffe7d783424a1
|
7
|
+
data.tar.gz: 33a9106e621be55c92dbaa585f31865755d6414e012fb6341e402d896d2ae66b4e3336418701ab2ef515048463393450868fb72a58986d98f766469782ff8bd5
|
data/lib/stan/client.rb
CHANGED
@@ -2,6 +2,7 @@ require 'stan/pb/protocol.pb'
|
|
2
2
|
require 'nats/io/client'
|
3
3
|
require 'securerandom'
|
4
4
|
require 'monitor'
|
5
|
+
require 'stan/version'
|
5
6
|
|
6
7
|
module STAN
|
7
8
|
|
@@ -24,12 +25,24 @@ module STAN
|
|
24
25
|
# Errors
|
25
26
|
class Error < StandardError; end
|
26
27
|
|
27
|
-
# When we
|
28
|
+
# When we get an error from the server during connect request
|
28
29
|
class ConnectError < Error; end
|
29
30
|
|
31
|
+
# When we cannot connect due to an invalid connection
|
32
|
+
class BadConnectionError < Error; end
|
33
|
+
|
30
34
|
# When we detect we have a request timeout
|
31
35
|
class TimeoutError < Error; end
|
32
36
|
|
37
|
+
# When we detect we cannot connect to NATS Streaming
|
38
|
+
class ConnectReqTimeoutError < TimeoutError; end
|
39
|
+
|
40
|
+
# When we timeout making a subscription
|
41
|
+
class SubReqTimeoutError < TimeoutError; end
|
42
|
+
|
43
|
+
# When we timeout closing session with NATS Streaming
|
44
|
+
class CloseReqTimeoutError < TimeoutError; end
|
45
|
+
|
33
46
|
class Client
|
34
47
|
include MonitorMixin
|
35
48
|
|
@@ -117,15 +130,15 @@ module STAN
|
|
117
130
|
end
|
118
131
|
|
119
132
|
# If no connection to NATS present at this point then bail already
|
120
|
-
raise
|
133
|
+
raise BadConnectionError.new("stan: invalid connection to nats") unless @nats
|
121
134
|
|
122
135
|
# Heartbeat subscription
|
123
136
|
@hb_inbox = (STAN.create_inbox).freeze
|
124
137
|
|
125
138
|
# Setup acks and heartbeats processing callbacks
|
126
|
-
@hb_inbox_sid = nats.subscribe(@hb_inbox) { |raw| process_heartbeats(raw) }
|
127
|
-
@ack_subject_sid = nats.subscribe(@ack_subject) { |raw| process_ack(raw) }
|
128
|
-
nats.flush
|
139
|
+
@hb_inbox_sid = nats.subscribe(@hb_inbox) { |raw, reply, subject| process_heartbeats(raw, reply, subject) }
|
140
|
+
@ack_subject_sid = nats.subscribe(@ack_subject) { |raw, reply, subject| process_ack(raw, reply, subject) }
|
141
|
+
nats.flush(options[:connect_timeout])
|
129
142
|
|
130
143
|
# Initial connect request to discover subjects to be used
|
131
144
|
# for communicating with STAN.
|
@@ -135,8 +148,24 @@ module STAN
|
|
135
148
|
})
|
136
149
|
|
137
150
|
# TODO: Check for error and bail if required
|
138
|
-
|
151
|
+
begin
|
152
|
+
raw = nats.request(@discover_subject, req.to_proto, timeout: options[:connect_timeout])
|
153
|
+
rescue NATS::IO::Timeout
|
154
|
+
raise ConnectReqTimeoutError.new("stan: failed connecting to '#{@cluster_id}'")
|
155
|
+
end
|
156
|
+
|
139
157
|
resp = STAN::Protocol::ConnectResponse.decode(raw.data)
|
158
|
+
unless resp.error.empty?
|
159
|
+
# We didn't really connect but we call closing in order to
|
160
|
+
# cleanup any other present state.
|
161
|
+
# FIXME: Errors happening here should be reported async
|
162
|
+
close rescue nil
|
163
|
+
|
164
|
+
raise ConnectError.new(resp.error)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Capture communication channels to STAN only when there
|
168
|
+
# have not been any errors when connecting.
|
140
169
|
@pub_prefix = resp.pubPrefix.freeze
|
141
170
|
@sub_req_subject = resp.subRequests.freeze
|
142
171
|
@unsub_req_subject = resp.unsubRequests.freeze
|
@@ -155,6 +184,8 @@ module STAN
|
|
155
184
|
|
156
185
|
# Publish will publish to the cluster and wait for an ack
|
157
186
|
def publish(subject, payload, opts={}, &blk)
|
187
|
+
raise BadConnectionError.new unless @pub_prefix
|
188
|
+
|
158
189
|
stan_subject = "#{@pub_prefix}.#{subject}"
|
159
190
|
future = nil
|
160
191
|
guid = STAN.create_guid
|
@@ -224,6 +255,8 @@ module STAN
|
|
224
255
|
|
225
256
|
# Create subscription which dispatches messages to callback asynchronously
|
226
257
|
def subscribe(subject, opts={}, &cb)
|
258
|
+
raise BadConnectionError.new unless @sub_req_subject
|
259
|
+
|
227
260
|
sub_options = {}
|
228
261
|
sub_options.merge!(opts)
|
229
262
|
sub_options[:ack_wait] ||= DEFAULT_ACK_WAIT
|
@@ -239,9 +272,10 @@ module STAN
|
|
239
272
|
# Listen for actual messages
|
240
273
|
sid = nats.subscribe(sub.inbox) { |raw, reply, subject| process_msg(raw, reply, subject) }
|
241
274
|
sub.sid = sid
|
242
|
-
nats.flush
|
275
|
+
nats.flush(options[:connect_timeout])
|
243
276
|
|
244
277
|
# Create the subscription request announcing the inbox on which
|
278
|
+
|
245
279
|
# we have made the NATS subscription for processing messages.
|
246
280
|
# First, we normalize customized subscription options before
|
247
281
|
# encoding to protobuf.
|
@@ -265,7 +299,7 @@ module STAN
|
|
265
299
|
end
|
266
300
|
|
267
301
|
unless response.error.empty?
|
268
|
-
# FIXME: Error handling on unsubscribe
|
302
|
+
# FIXME: Error handling on unsubscribe should be async
|
269
303
|
nats.unsubscribe(sub.sid)
|
270
304
|
raise Error.new(response.error)
|
271
305
|
end
|
@@ -275,23 +309,31 @@ module STAN
|
|
275
309
|
|
276
310
|
return sub
|
277
311
|
end
|
312
|
+
rescue NATS::IO::Timeout
|
313
|
+
raise SubReqTimeoutError.new("stan: subscribe request timeout on '#{subject}'")
|
278
314
|
end
|
279
315
|
|
280
316
|
# Close wraps us the session with the NATS Streaming server
|
281
317
|
def close
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
318
|
+
# Send close when going away only if we have been able to successfully connect
|
319
|
+
if @close_req_subject
|
320
|
+
req = STAN::Protocol::CloseRequest.new(clientID: @client_id)
|
321
|
+
raw = nats.request(@close_req_subject, req.to_proto, timeout: options[:connect_timeout])
|
322
|
+
|
323
|
+
resp = STAN::Protocol::CloseResponse.decode(raw.data)
|
324
|
+
unless resp.error.empty?
|
325
|
+
raise Error.new(resp.error)
|
326
|
+
end
|
288
327
|
end
|
289
328
|
|
329
|
+
# If we do not even have a connection then return already...
|
330
|
+
return unless @nats
|
331
|
+
|
290
332
|
# TODO: If connection to nats was borrowed then we should
|
291
333
|
# unsubscribe from all topics from STAN. If not borrowed
|
292
334
|
# and we own the connection, then we just close.
|
293
335
|
begin
|
294
|
-
# Remove all
|
336
|
+
# Remove all related subscriptions for STAN
|
295
337
|
@sub_map.each_pair do |_, sub|
|
296
338
|
nats.unsubscribe(sub.sid)
|
297
339
|
end
|
@@ -299,8 +341,9 @@ module STAN
|
|
299
341
|
# Finally, remove the core subscriptions for STAN
|
300
342
|
nats.unsubscribe(@hb_inbox_sid)
|
301
343
|
nats.unsubscribe(@ack_subject_sid)
|
302
|
-
|
303
|
-
|
344
|
+
nats.flush(options[:connect_timeout])
|
345
|
+
rescue NATS::IO::Timeout
|
346
|
+
raise CloseReqTimeoutError.new("stan: close request timeout")
|
304
347
|
ensure
|
305
348
|
if @borrowed_nats_connection
|
306
349
|
@nats = nil
|
@@ -322,10 +365,14 @@ module STAN
|
|
322
365
|
end
|
323
366
|
end
|
324
367
|
|
368
|
+
def to_s
|
369
|
+
%Q(#<STAN::Client @cluster_id="#{@cluster_id}" @client_id="#{@client_id}">)
|
370
|
+
end
|
371
|
+
|
325
372
|
private
|
326
373
|
|
327
374
|
# Process received publishes acks
|
328
|
-
def process_ack(data)
|
375
|
+
def process_ack(data, reply, subject)
|
329
376
|
# FIXME: This should handle errors asynchronously in case there are any
|
330
377
|
|
331
378
|
# Process ack
|
@@ -392,6 +439,7 @@ module STAN
|
|
392
439
|
sub_opts[:qGroup] = opts[:queue] if opts[:queue]
|
393
440
|
sub_opts[:durableName] = opts[:durable_name] if opts[:durable_name]
|
394
441
|
|
442
|
+
# Must announce the clientID as part of the protocol in each subscription
|
395
443
|
sub_opts[:clientID] = @client_id
|
396
444
|
sub_opts[:maxInFlight] = opts[:max_inflight]
|
397
445
|
sub_opts[:ackWaitInSecs] = opts[:ack_wait] || opts[:ack_timeout]
|
@@ -440,6 +488,10 @@ module STAN
|
|
440
488
|
@durable_name = opts[:durable_name]
|
441
489
|
end
|
442
490
|
|
491
|
+
def to_s
|
492
|
+
%Q(#<STAN::Subscription @subject="#{@subject}" @queue="#{@queue}" @durable_name="#{@durable_name}" @inbox="#{@inbox}" @ack_inbox="#{@ack_inbox}" @sid=#{@sid}>)
|
493
|
+
end
|
494
|
+
|
443
495
|
# Unsubscribe removes interest in the subscription.
|
444
496
|
# For durables, it means that the durable interest is also removed from
|
445
497
|
# the server. Restarting a durable with the same name will not resume
|
@@ -508,15 +560,25 @@ module STAN
|
|
508
560
|
end
|
509
561
|
|
510
562
|
# Data holder for sent messages
|
511
|
-
# It should have an Ack method as well to reply back?
|
512
|
-
Msg = Struct.new(:proto, :sub) do
|
563
|
+
# FIXME: It should have an Ack method as well to reply back?
|
564
|
+
::STAN::Msg = Struct.new(:proto, :sub) do
|
513
565
|
def data
|
514
566
|
self.proto.data
|
515
567
|
end
|
516
568
|
def sequence
|
517
569
|
self.proto.sequence
|
518
570
|
end
|
571
|
+
def timestamp
|
572
|
+
self.proto.timestamp
|
573
|
+
end
|
574
|
+
def time
|
575
|
+
self.proto.timestamp / 1_000_000_000.0
|
576
|
+
end
|
519
577
|
alias seq sequence
|
578
|
+
|
579
|
+
def to_s
|
580
|
+
"#<STAN::Msg sequence=#{self.sequence} time=#{self.time.to_f} data=#{self.data}>"
|
581
|
+
end
|
520
582
|
end
|
521
583
|
|
522
584
|
class << self
|
data/lib/stan/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nats-streaming
|
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:
|
11
|
+
date: 2017-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nats-pure
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: google-protobuf
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '3'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '3'
|
41
41
|
description: Ruby client for the NATS Streaming messaging system.
|
42
42
|
email:
|
43
43
|
- wally@apcera.com
|
@@ -68,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
68
|
version: '0'
|
69
69
|
requirements: []
|
70
70
|
rubyforge_project:
|
71
|
-
rubygems_version: 2.
|
71
|
+
rubygems_version: 2.6.8
|
72
72
|
signing_key:
|
73
73
|
specification_version: 4
|
74
74
|
summary: Ruby client for the NATS Streaming messaging system.
|