nats-streaming 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2b4619f24307110860a56b03d04b15be8c8f35b3
4
+ data.tar.gz: 79e03889f056cfbd5fb64491c236ffe66b99f4e9
5
+ SHA512:
6
+ metadata.gz: 64d4045d951790d2207aa80cc5732b0f08078f7fe244f5ea033663c74a70f901d78e5015758300fa198a7fb35457fb70ad0f5a311ca0be83a6ccaae37ef745f4
7
+ data.tar.gz: 7cbbcef0b8ab55e53b8ca2124427ff41f77356eb326d775106249ea58c880cea88dd065657df323289abea2e7dbae517cb6383be4a26133a35857355b6cfbafc
@@ -0,0 +1,531 @@
1
+ require 'stan/pb/protocol.pb'
2
+ require 'nats/io/client'
3
+ require 'securerandom'
4
+ require 'monitor'
5
+
6
+ module STAN
7
+
8
+ # Subject namespaces for clients to ack and connect
9
+ DEFAULT_ACKS_SUBJECT = "_STAN.acks".freeze
10
+ DEFAULT_DISCOVER_SUBJECT = "_STAN.discover".freeze
11
+
12
+ # Ack timeout in seconds
13
+ DEFAULT_ACK_WAIT = 30
14
+
15
+ # Max number of inflight acks from received messages
16
+ DEFAULT_MAX_INFLIGHT = 1024
17
+
18
+ # Connect timeout in seconds
19
+ DEFAULT_CONNECT_TIMEOUT = 2
20
+
21
+ # Max number of inflight pub acks
22
+ DEFAULT_MAX_PUB_ACKS_INFLIGHT = 16384
23
+
24
+ # Errors
25
+ class Error < StandardError; end
26
+
27
+ # When we detect we cannot connect to the server
28
+ class ConnectError < Error; end
29
+
30
+ # When we detect we have a request timeout
31
+ class TimeoutError < Error; end
32
+
33
+ class Client
34
+ include MonitorMixin
35
+
36
+ attr_reader :nats, :options, :client_id, :sub_map, :unsub_req_subject, :sub_close_req_subject, :pending_pub_acks
37
+
38
+ def initialize
39
+ super
40
+
41
+ # Connection to NATS, either owned or borrowed
42
+ @nats = nil
43
+ @borrowed_nats_connection = false
44
+
45
+ # STAN subscriptions map
46
+ @sub_map = {}
47
+
48
+ # Publish Ack map (guid => ack)
49
+ @pub_ack_map = {}
50
+ @pending_pub_acks = nil
51
+
52
+ # Cluster to which we are connecting
53
+ @cluster_id = nil
54
+ @client_id = nil
55
+
56
+ # Connect options
57
+ @options = {}
58
+
59
+ # NATS Streaming subjects
60
+
61
+ # Inbox subscription for periodical heartbeat messages
62
+ @hb_inbox = nil
63
+ @hb_inbox_sid = nil
64
+
65
+ # Subscription for processing received acks from the server
66
+ @ack_subject = nil
67
+ @ack_subject_sid = nil
68
+
69
+ # Publish prefix set by stan to which we append our subject on publish.
70
+ @pub_prefix = nil
71
+ @sub_req_subject = nil
72
+ @unsub_req_subject = nil
73
+ @close_req_subject = nil
74
+ @sub_close_req_subject = nil
75
+
76
+ # For initial connect request to discover subjects used by
77
+ # the streaming server.
78
+ @discover_subject = nil
79
+ end
80
+
81
+ # Plugs into a NATS Streaming cluster, establishing a connection
82
+ # to NATS in case there is not one available to be borrowed.
83
+ def connect(cluster_id, client_id, opts={}, &blk)
84
+ @cluster_id = cluster_id
85
+ @client_id = client_id
86
+ @options = opts
87
+
88
+ # Defaults
89
+ @options[:connect_timeout] ||= DEFAULT_CONNECT_TIMEOUT
90
+ @options[:max_pub_acks_inflight] ||= DEFAULT_MAX_PUB_ACKS_INFLIGHT
91
+
92
+ # Buffered queue for controlling inflight published acks
93
+ @pending_pub_acks = SizedQueue.new(options[:max_pub_acks_inflight])
94
+
95
+ # Prepare connect discovery request
96
+ @discover_subject = "#{DEFAULT_DISCOVER_SUBJECT}.#{@cluster_id}".freeze
97
+
98
+ # Prepare delivered msgs acks processing subscription
99
+ @ack_subject = "#{DEFAULT_ACKS_SUBJECT}.#{STAN.create_guid}".freeze
100
+
101
+ if @nats.nil?
102
+ case options[:nats]
103
+ when Hash
104
+ # Custom NATS options in case borrowed connection not present
105
+ # can be passed to establish a connection and have stan client
106
+ # owning it.
107
+ @nats = NATS::IO::Client.new
108
+ nats.connect(options[:nats])
109
+ when NATS::IO::Client
110
+ @nats = options[:nats]
111
+ @borrowed_nats_connection = true
112
+ else
113
+ # Try to connect with NATS defaults
114
+ @nats = NATS::IO::Client.new
115
+ nats.connect(servers: ["nats://127.0.0.1:4222"])
116
+ end
117
+ end
118
+
119
+ # If no connection to NATS present at this point then bail already
120
+ raise ConnectError.new("stan: invalid connection to nats") unless @nats
121
+
122
+ # Heartbeat subscription
123
+ @hb_inbox = (STAN.create_inbox).freeze
124
+
125
+ # 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
129
+
130
+ # Initial connect request to discover subjects to be used
131
+ # for communicating with STAN.
132
+ req = STAN::Protocol::ConnectRequest.new({
133
+ clientID: @client_id,
134
+ heartbeatInbox: @hb_inbox
135
+ })
136
+
137
+ # TODO: Check for error and bail if required
138
+ raw = nats.request(@discover_subject, req.to_proto, timeout: options[:connect_timeout])
139
+ resp = STAN::Protocol::ConnectResponse.decode(raw.data)
140
+ @pub_prefix = resp.pubPrefix.freeze
141
+ @sub_req_subject = resp.subRequests.freeze
142
+ @unsub_req_subject = resp.unsubRequests.freeze
143
+ @close_req_subject = resp.closeRequests.freeze
144
+ @sub_close_req_subject = resp.subCloseRequests.freeze
145
+
146
+ # If callback given then we send a close request on exit
147
+ # and wrap up session to STAN.
148
+ if blk
149
+ blk.call(self)
150
+
151
+ # Close session to the STAN cluster
152
+ close
153
+ end
154
+ end
155
+
156
+ # Publish will publish to the cluster and wait for an ack
157
+ def publish(subject, payload, opts={}, &blk)
158
+ stan_subject = "#{@pub_prefix}.#{subject}"
159
+ future = nil
160
+ guid = STAN.create_guid
161
+
162
+ pe = STAN::Protocol::PubMsg.new({
163
+ clientID: @client_id,
164
+ guid: guid,
165
+ subject: subject,
166
+ data: payload
167
+ })
168
+
169
+ # Use buffered queue to control number of outstanding acks
170
+ @pending_pub_acks << :ack
171
+
172
+ if blk
173
+ # Asynchronously handled if block given
174
+ synchronize do
175
+ # Map ack to guid
176
+ @pub_ack_map[guid] = proc do |ack|
177
+ # If block is given, handle the result asynchronously
178
+ error = ack.error.empty? ? nil : Error.new(ack.error)
179
+ case blk.arity
180
+ when 0 then blk.call
181
+ when 1 then blk.call(ack.guid)
182
+ when 2 then blk.call(ack.guid, error)
183
+ end
184
+
185
+ @pub_ack_map.delete(ack.guid)
186
+ end
187
+
188
+ nats.publish(stan_subject, pe.to_proto, @ack_subject)
189
+ end
190
+ else
191
+ # No block means waiting for response before giving back control
192
+ future = new_cond
193
+ opts[:timeout] ||= DEFAULT_ACK_WAIT
194
+
195
+ synchronize do
196
+ # Map ack to guid
197
+ ack_response = nil
198
+
199
+ # FIXME: Maybe use fiber instead?
200
+ @pub_ack_map[guid] = proc do |ack|
201
+ # Capture the ack response
202
+ ack_response = ack
203
+ future.signal
204
+ end
205
+
206
+ # Send publish request and wait for the ack response
207
+ nats.publish(stan_subject, pe.to_proto, @ack_subject)
208
+ start_time = NATS::MonotonicTime.now
209
+ future.wait(opts[:timeout])
210
+ end_time = NATS::MonotonicTime.now
211
+ if (end_time - start_time) > opts[:timeout]
212
+ # Remove ack
213
+ @pub_ack_map.delete(guid)
214
+ raise TimeoutError.new("stan: timeout")
215
+ end
216
+
217
+ # Remove ack
218
+ @pub_ack_map.delete(guid)
219
+ return guid
220
+ end
221
+ end
222
+ # TODO: Loop for processing of expired acks
223
+ end
224
+
225
+ # Create subscription which dispatches messages to callback asynchronously
226
+ def subscribe(subject, opts={}, &cb)
227
+ sub_options = {}
228
+ sub_options.merge!(opts)
229
+ sub_options[:ack_wait] ||= DEFAULT_ACK_WAIT
230
+ sub_options[:max_inflight] ||= DEFAULT_MAX_INFLIGHT
231
+ sub_options[:stan] = self
232
+
233
+ sub = Subscription.new(subject, sub_options, cb)
234
+ sub.extend(MonitorMixin)
235
+ synchronize { @sub_map[sub.inbox] = sub }
236
+
237
+ # Hold lock throughout
238
+ sub.synchronize do
239
+ # Listen for actual messages
240
+ sid = nats.subscribe(sub.inbox) { |raw, reply, subject| process_msg(raw, reply, subject) }
241
+ sub.sid = sid
242
+ nats.flush
243
+
244
+ # Create the subscription request announcing the inbox on which
245
+ # we have made the NATS subscription for processing messages.
246
+ # First, we normalize customized subscription options before
247
+ # encoding to protobuf.
248
+ sub_opts = normalize_sub_req_params(sub_options)
249
+
250
+ # Set STAN subject and NATS inbox where we will be awaiting
251
+ # for the messages to be delivered.
252
+ sub_opts[:subject] = subject
253
+ sub_opts[:inbox] = sub.inbox
254
+
255
+ sr = STAN::Protocol::SubscriptionRequest.new(sub_opts)
256
+ reply = nil
257
+ response = nil
258
+ begin
259
+ reply = nats.request(@sub_req_subject, sr.to_proto, timeout: options[:connect_timeout])
260
+ response = STAN::Protocol::SubscriptionResponse.decode(reply.data)
261
+ rescue NATS::IO::Timeout, Google::Protobuf::ParseError => e
262
+ # FIXME: Error handling on unsubscribe
263
+ nats.unsubscribe(sub.sid)
264
+ raise e
265
+ end
266
+
267
+ unless response.error.empty?
268
+ # FIXME: Error handling on unsubscribe
269
+ nats.unsubscribe(sub.sid)
270
+ raise Error.new(response.error)
271
+ end
272
+
273
+ # Capture ack inbox for the subscription
274
+ sub.ack_inbox = response.ackInbox.freeze
275
+
276
+ return sub
277
+ end
278
+ end
279
+
280
+ # Close wraps us the session with the NATS Streaming server
281
+ def close
282
+ req = STAN::Protocol::CloseRequest.new(clientID: @client_id)
283
+ raw = nats.request(@close_req_subject, req.to_proto)
284
+
285
+ resp = STAN::Protocol::CloseResponse.decode(raw.data)
286
+ unless resp.error.empty?
287
+ raise Error.new(resp.error)
288
+ end
289
+
290
+ # TODO: If connection to nats was borrowed then we should
291
+ # unsubscribe from all topics from STAN. If not borrowed
292
+ # and we own the connection, then we just close.
293
+ begin
294
+ # Remove all present subscriptions
295
+ @sub_map.each_pair do |_, sub|
296
+ nats.unsubscribe(sub.sid)
297
+ end
298
+
299
+ # Finally, remove the core subscriptions for STAN
300
+ nats.unsubscribe(@hb_inbox_sid)
301
+ nats.unsubscribe(@ack_subject_sid)
302
+ rescue => e
303
+ # TODO: Async error handling
304
+ ensure
305
+ if @borrowed_nats_connection
306
+ @nats = nil
307
+ else
308
+ @nats.close
309
+ end
310
+ end
311
+ end
312
+
313
+ # Ack takes a received message and publishes an ack manually
314
+ def ack(msg)
315
+ return unless msg.sub
316
+ msg.sub.synchronize do
317
+ ack_proto = STAN::Protocol::Ack.new({
318
+ subject: msg.proto.subject,
319
+ sequence: msg.proto.sequence
320
+ }).to_proto
321
+ nats.publish(msg.sub.ack_inbox, ack_proto)
322
+ end
323
+ end
324
+
325
+ private
326
+
327
+ # Process received publishes acks
328
+ def process_ack(data)
329
+ # FIXME: This should handle errors asynchronously in case there are any
330
+
331
+ # Process ack
332
+ pub_ack = STAN::Protocol::PubAck.decode(data)
333
+ unless pub_ack.error.empty?
334
+ raise Error.new(pub_ack.error)
335
+ end
336
+
337
+ # Unblock publishing queue
338
+ @pending_pub_acks.pop if @pending_pub_acks.size > 0
339
+
340
+ synchronize do
341
+ # yield the ack response back to original publisher caller
342
+ if cb = @pub_ack_map[pub_ack.guid]
343
+ cb.call(pub_ack)
344
+ end
345
+ end
346
+ end
347
+
348
+ # Process heartbeats by replying to them
349
+ def process_heartbeats(data, reply, subject)
350
+ # No payload assumed, just reply to the heartbeat.
351
+ nats.publish(reply, '')
352
+ end
353
+
354
+ # Process any received messages
355
+ def process_msg(data, reply, subject)
356
+ msg = Msg.new
357
+ msg.proto = STAN::Protocol::MsgProto.decode(data)
358
+ msg_ack = STAN::Protocol::Ack.new({
359
+ subject: msg.proto.subject,
360
+ sequence: msg.proto.sequence
361
+ })
362
+
363
+ # Lookup the subscription
364
+ sub = nil
365
+ synchronize do
366
+ sub = @sub_map[subject]
367
+ end
368
+ # Check if sub is no longer valid
369
+ return unless sub
370
+
371
+ # Store in msg for backlink
372
+ msg.sub = sub
373
+
374
+ cb = nil
375
+ ack_subject = nil
376
+ using_manual_acks = nil
377
+ sub.synchronize do
378
+ cb = sub.cb
379
+ ack_subject = sub.ack_inbox
380
+ using_manual_acks = sub.options[:manual_acks]
381
+ end
382
+
383
+ # Perform the callback if sub still subscribed
384
+ cb.call(msg) if cb
385
+
386
+ # Process auto-ack if not done manually
387
+ nats.publish(ack_subject, msg_ack.to_proto) if not using_manual_acks
388
+ end
389
+
390
+ def normalize_sub_req_params(opts)
391
+ sub_opts = {}
392
+ sub_opts[:qGroup] = opts[:queue] if opts[:queue]
393
+ sub_opts[:durableName] = opts[:durable_name] if opts[:durable_name]
394
+
395
+ sub_opts[:clientID] = @client_id
396
+ sub_opts[:maxInFlight] = opts[:max_inflight]
397
+ sub_opts[:ackWaitInSecs] = opts[:ack_wait] || opts[:ack_timeout]
398
+
399
+ # TODO: Error checking when all combinations of options are not declared
400
+ case opts[:start_at]
401
+ when :new_only
402
+ # By default, it already acts as :new_only which is
403
+ # without no initial replay, similar to bare NATS,
404
+ # but we allow setting it explicitly anyway.
405
+ sub_opts[:startPosition] = :NewOnly
406
+ when :last_received
407
+ sub_opts[:startPosition] = :LastReceived
408
+ when :time, :timedelta
409
+ # If using timedelta, need to get current time in UnixNano format
410
+ # FIXME: Implement support for :ago option which uses time in human.
411
+ sub_opts[:startPosition] = :TimeDeltaStart
412
+ start_at_time = opts[:time] * 1_000_000_000
413
+ sub_opts[:startTimeDelta] = (Time.now.to_f * 1_000_000_000) - start_at_time
414
+ when :sequence
415
+ sub_opts[:startPosition] = :SequenceStart
416
+ sub_opts[:startSequence] = opts[:sequence] || 0
417
+ when :first, :beginning
418
+ sub_opts[:startPosition] = :First
419
+ else
420
+ sub_opts[:startPosition] = :First if opts[:deliver_all_available]
421
+ end
422
+
423
+ sub_opts
424
+ end
425
+ end
426
+
427
+ class Subscription
428
+ attr_reader :subject, :queue, :inbox, :options, :cb, :durable_name, :stan
429
+ attr_accessor :sid, :ack_inbox
430
+
431
+ def initialize(subject, opts={}, cb)
432
+ @subject = subject
433
+ @queue = opts[:queue]
434
+ @inbox = STAN.create_inbox
435
+ @sid = nil # inbox subscription sid
436
+ @options = opts
437
+ @cb = cb
438
+ @ack_inbox = nil
439
+ @stan = opts[:stan]
440
+ @durable_name = opts[:durable_name]
441
+ end
442
+
443
+ # Unsubscribe removes interest in the subscription.
444
+ # For durables, it means that the durable interest is also removed from
445
+ # the server. Restarting a durable with the same name will not resume
446
+ # the subscription, it will be considered a new one.
447
+ def unsubscribe
448
+ synchronize do
449
+ stan.nats.unsubscribe(self.sid)
450
+ end
451
+
452
+ # Make client stop tracking the subscription inbox
453
+ # and grab unsub request subject under the lock.
454
+ unsub_subject = nil
455
+ stan.synchronize do
456
+ stan.sub_map.delete(self.ack_inbox)
457
+ unsub_subject = stan.unsub_req_subject
458
+ end
459
+
460
+ unsub_req = STAN::Protocol::UnsubscribeRequest.new({
461
+ clientID: stan.client_id,
462
+ subject: self.subject,
463
+ inbox: self.ack_inbox
464
+ })
465
+
466
+ if self.durable_name
467
+ unsub_req[:durableName] = self.durable_name
468
+ end
469
+
470
+ raw = stan.nats.request(unsub_subject, unsub_req.to_proto, {
471
+ timeout: stan.options[:connect_timeout]
472
+ })
473
+ response = STAN::Protocol::SubscriptionResponse.decode(raw.data)
474
+ unless response.error.empty?
475
+ # FIXME: Error handling on unsubscribe
476
+ raise Error.new(response.error)
477
+ end
478
+ end
479
+
480
+ def close
481
+ synchronize do
482
+ stan.nats.unsubscribe(self.sid)
483
+ end
484
+
485
+ # Make client stop tracking the subscription inbox
486
+ # and grab close request subject under the lock.
487
+ sub_close_subject = nil
488
+ stan.synchronize do
489
+ stan.sub_map.delete(self.ack_inbox)
490
+ sub_close_subject = stan.sub_close_req_subject
491
+ end
492
+
493
+ sub_close_req = STAN::Protocol::UnsubscribeRequest.new({
494
+ clientID: stan.client_id,
495
+ subject: self.subject,
496
+ inbox: self.ack_inbox
497
+ })
498
+
499
+ raw = stan.nats.request(sub_close_subject, sub_close_req.to_proto, {
500
+ timeout: stan.options[:connect_timeout]
501
+ })
502
+ response = STAN::Protocol::SubscriptionResponse.decode(raw.data)
503
+ unless response.error.empty?
504
+ # FIXME: Error handling on unsubscribe/close
505
+ raise Error.new(response.error)
506
+ end
507
+ end
508
+ end
509
+
510
+ # Data holder for sent messages
511
+ # It should have an Ack method as well to reply back?
512
+ Msg = Struct.new(:proto, :sub) do
513
+ def data
514
+ self.proto.data
515
+ end
516
+ def sequence
517
+ self.proto.sequence
518
+ end
519
+ alias seq sequence
520
+ end
521
+
522
+ class << self
523
+ def create_guid
524
+ SecureRandom.hex(11)
525
+ end
526
+
527
+ def create_inbox
528
+ SecureRandom.hex(13)
529
+ end
530
+ end
531
+ end
@@ -0,0 +1,97 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: pb/protocol.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "STAN.Protocol.PubMsg" do
8
+ optional :clientID, :string, 1
9
+ optional :guid, :string, 2
10
+ optional :subject, :string, 3
11
+ optional :reply, :string, 4
12
+ optional :data, :bytes, 5
13
+ optional :sha256, :bytes, 10
14
+ end
15
+ add_message "STAN.Protocol.PubAck" do
16
+ optional :guid, :string, 1
17
+ optional :error, :string, 2
18
+ end
19
+ add_message "STAN.Protocol.MsgProto" do
20
+ optional :sequence, :uint64, 1
21
+ optional :subject, :string, 2
22
+ optional :reply, :string, 3
23
+ optional :data, :bytes, 4
24
+ optional :timestamp, :int64, 5
25
+ optional :redelivered, :bool, 6
26
+ optional :CRC32, :uint32, 10
27
+ end
28
+ add_message "STAN.Protocol.Ack" do
29
+ optional :subject, :string, 1
30
+ optional :sequence, :uint64, 2
31
+ end
32
+ add_message "STAN.Protocol.ConnectRequest" do
33
+ optional :clientID, :string, 1
34
+ optional :heartbeatInbox, :string, 2
35
+ end
36
+ add_message "STAN.Protocol.ConnectResponse" do
37
+ optional :pubPrefix, :string, 1
38
+ optional :subRequests, :string, 2
39
+ optional :unsubRequests, :string, 3
40
+ optional :closeRequests, :string, 4
41
+ optional :error, :string, 5
42
+ optional :subCloseRequests, :string, 6
43
+ optional :publicKey, :string, 100
44
+ end
45
+ add_message "STAN.Protocol.SubscriptionRequest" do
46
+ optional :clientID, :string, 1
47
+ optional :subject, :string, 2
48
+ optional :qGroup, :string, 3
49
+ optional :inbox, :string, 4
50
+ optional :maxInFlight, :int32, 5
51
+ optional :ackWaitInSecs, :int32, 6
52
+ optional :durableName, :string, 7
53
+ optional :startPosition, :enum, 10, "STAN.Protocol.StartPosition"
54
+ optional :startSequence, :uint64, 11
55
+ optional :startTimeDelta, :int64, 12
56
+ end
57
+ add_message "STAN.Protocol.SubscriptionResponse" do
58
+ optional :ackInbox, :string, 2
59
+ optional :error, :string, 3
60
+ end
61
+ add_message "STAN.Protocol.UnsubscribeRequest" do
62
+ optional :clientID, :string, 1
63
+ optional :subject, :string, 2
64
+ optional :inbox, :string, 3
65
+ optional :durableName, :string, 4
66
+ end
67
+ add_message "STAN.Protocol.CloseRequest" do
68
+ optional :clientID, :string, 1
69
+ end
70
+ add_message "STAN.Protocol.CloseResponse" do
71
+ optional :error, :string, 1
72
+ end
73
+ add_enum "STAN.Protocol.StartPosition" do
74
+ value :NewOnly, 0
75
+ value :LastReceived, 1
76
+ value :TimeDeltaStart, 2
77
+ value :SequenceStart, 3
78
+ value :First, 4
79
+ end
80
+ end
81
+
82
+ module STAN
83
+ module Protocol
84
+ PubMsg = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.PubMsg").msgclass
85
+ PubAck = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.PubAck").msgclass
86
+ MsgProto = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.MsgProto").msgclass
87
+ Ack = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.Ack").msgclass
88
+ ConnectRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.ConnectRequest").msgclass
89
+ ConnectResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.ConnectResponse").msgclass
90
+ SubscriptionRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.SubscriptionRequest").msgclass
91
+ SubscriptionResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.SubscriptionResponse").msgclass
92
+ UnsubscribeRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.UnsubscribeRequest").msgclass
93
+ CloseRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.CloseRequest").msgclass
94
+ CloseResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.CloseResponse").msgclass
95
+ StartPosition = Google::Protobuf::DescriptorPool.generated_pool.lookup("STAN.Protocol.StartPosition").enummodule
96
+ end
97
+ end
@@ -0,0 +1,3 @@
1
+ module STAN
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nats-streaming
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Waldemar Quevedo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nats-pure
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: google-protobuf
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Ruby client for the NATS Streaming messaging system.
42
+ email:
43
+ - wally@apcera.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/stan/client.rb
49
+ - lib/stan/pb/protocol.pb.rb
50
+ - lib/stan/version.rb
51
+ homepage: https://nats.io
52
+ licenses:
53
+ - MIT
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 2.5.2
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: Ruby client for the NATS Streaming messaging system.
75
+ test_files: []