nats-streaming 0.1.0 → 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/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.
|