nats-pure 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nats/io/client.rb +89 -14
- data/lib/nats/io/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59129f0c5e0180f95490a2ca5e2acb8cf0c1d630c32e4d4ab6f0cf859242500b
|
4
|
+
data.tar.gz: c23db05317523a59762b9b2e73917165baf8ee3a898aaa74e84a74b0977c1942
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b82fdc592bea6ddc5ca1e0792b76071dd09db70a86fcaef517207d33c339d1b105076efd2b3d3cc83960a6b470739d01ec9d2f41574f57111935e0245eb02e5d
|
7
|
+
data.tar.gz: 4439c2f2f0c3c6118b5a4b93587a60ecb069f8b85e0907539bec6a497a8394a1f78a9a961aa2565436e7c7ab4ee3bc1bd459310935499da67c1d7e7c11a0d5c7
|
data/lib/nats/io/client.rb
CHANGED
@@ -39,6 +39,10 @@ module NATS
|
|
39
39
|
DEFAULT_CONNECT_TIMEOUT = 2
|
40
40
|
DEFAULT_READ_WRITE_TIMEOUT = 2
|
41
41
|
|
42
|
+
# Default Pending Limits
|
43
|
+
DEFAULT_SUB_PENDING_MSGS_LIMIT = 65536
|
44
|
+
DEFAULT_SUB_PENDING_BYTES_LIMIT = 65536 * 1024
|
45
|
+
|
42
46
|
CR_LF = ("\r\n".freeze)
|
43
47
|
CR_LF_SIZE = (CR_LF.bytesize)
|
44
48
|
|
@@ -84,6 +88,9 @@ module NATS
|
|
84
88
|
# When we use an invalid subject.
|
85
89
|
class BadSubject < Error; end
|
86
90
|
|
91
|
+
# When a subscription hits the pending messages limit.
|
92
|
+
class SlowConsumer < Error; end
|
93
|
+
|
87
94
|
class Client
|
88
95
|
include MonitorMixin
|
89
96
|
|
@@ -286,11 +293,17 @@ module NATS
|
|
286
293
|
sid = (@ssid += 1)
|
287
294
|
sub = @subs[sid] = Subscription.new
|
288
295
|
end
|
296
|
+
opts[:pending_msgs_limit] ||= DEFAULT_SUB_PENDING_MSGS_LIMIT
|
297
|
+
opts[:pending_bytes_limit] ||= DEFAULT_SUB_PENDING_BYTES_LIMIT
|
298
|
+
|
289
299
|
sub.subject = subject
|
290
300
|
sub.callback = callback
|
291
301
|
sub.received = 0
|
292
302
|
sub.queue = opts[:queue] if opts[:queue]
|
293
303
|
sub.max = opts[:max] if opts[:max]
|
304
|
+
sub.pending_msgs_limit = opts[:pending_msgs_limit]
|
305
|
+
sub.pending_bytes_limit = opts[:pending_bytes_limit]
|
306
|
+
sub.pending_queue = SizedQueue.new(sub.pending_msgs_limit)
|
294
307
|
|
295
308
|
send_command("SUB #{subject} #{opts[:queue]} #{sid}#{CR_LF}")
|
296
309
|
@flush_queue << :sub
|
@@ -298,6 +311,36 @@ module NATS
|
|
298
311
|
# Setup server support for auto-unsubscribe when receiving enough messages
|
299
312
|
unsubscribe(sid, opts[:max]) if opts[:max]
|
300
313
|
|
314
|
+
# Async subscriptions each own a single thread for the
|
315
|
+
# delivery of messages.
|
316
|
+
# FIXME: Support shared thread pool with configurable limits
|
317
|
+
# to better support case of having a lot of subscriptions.
|
318
|
+
sub.wait_for_msgs_t = Thread.new do
|
319
|
+
loop do
|
320
|
+
msg = sub.pending_queue.pop
|
321
|
+
|
322
|
+
cb = nil
|
323
|
+
sub.synchronize do
|
324
|
+
# Decrease pending size since consumed already
|
325
|
+
sub.pending_size -= msg.data.size
|
326
|
+
cb = sub.callback
|
327
|
+
end
|
328
|
+
|
329
|
+
begin
|
330
|
+
case cb.arity
|
331
|
+
when 0 then cb.call
|
332
|
+
when 1 then cb.call(msg.data)
|
333
|
+
when 2 then cb.call(msg.data, msg.reply)
|
334
|
+
else cb.call(msg.data, msg.reply, msg.subject)
|
335
|
+
end
|
336
|
+
rescue => e
|
337
|
+
synchronize do
|
338
|
+
@err_cb.call(e) if @err_cb
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
301
344
|
sid
|
302
345
|
end
|
303
346
|
|
@@ -369,6 +412,12 @@ module NATS
|
|
369
412
|
synchronize do
|
370
413
|
sub.max = opt_max
|
371
414
|
@subs.delete(sid) unless (sub.max && (sub.received < sub.max))
|
415
|
+
|
416
|
+
# Stop messages delivery thread for async subscribers
|
417
|
+
if sub.wait_for_msgs_t && sub.wait_for_msgs_t.alive?
|
418
|
+
sub.wait_for_msgs_t.exit
|
419
|
+
sub.pending_queue.clear
|
420
|
+
end
|
372
421
|
end
|
373
422
|
end
|
374
423
|
|
@@ -446,9 +495,11 @@ module NATS
|
|
446
495
|
synchronize { sub = @subs[sid] }
|
447
496
|
return unless sub
|
448
497
|
|
449
|
-
|
498
|
+
sc = nil
|
450
499
|
sub.synchronize do
|
451
500
|
sub.received += 1
|
501
|
+
|
502
|
+
# Check for auto_unsubscribe
|
452
503
|
if sub.max
|
453
504
|
case
|
454
505
|
when sub.received > sub.max
|
@@ -469,20 +520,25 @@ module NATS
|
|
469
520
|
future.signal
|
470
521
|
|
471
522
|
return
|
523
|
+
elsif sub.callback
|
524
|
+
# Async subscribers use a sized queue for processing
|
525
|
+
# and should be able to consume messages in parallel.
|
526
|
+
if sub.pending_queue.size >= sub.pending_msgs_limit \
|
527
|
+
or sub.pending_size >= sub.pending_bytes_limit then
|
528
|
+
sc = SlowConsumer.new("nats: slow consumer, messages dropped")
|
529
|
+
else
|
530
|
+
# Only dispatch message when sure that it would not block
|
531
|
+
# the main read loop from the parser.
|
532
|
+
sub.pending_queue << Msg.new(subject, reply, data)
|
533
|
+
sub.pending_size += data.size
|
534
|
+
end
|
472
535
|
end
|
473
536
|
end
|
474
537
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
case cb.arity
|
480
|
-
when 0 then cb.call
|
481
|
-
when 1 then cb.call(data)
|
482
|
-
when 2 then cb.call(data, reply)
|
483
|
-
else cb.call(data, reply, subject)
|
484
|
-
end
|
485
|
-
end
|
538
|
+
synchronize do
|
539
|
+
@last_err = sc
|
540
|
+
@err_cb.call(sc) if @err_cb
|
541
|
+
end if sc
|
486
542
|
end
|
487
543
|
|
488
544
|
def process_info(line)
|
@@ -998,7 +1054,15 @@ module NATS
|
|
998
1054
|
@err_cb.call(e) if @err_cb
|
999
1055
|
end if should_flush
|
1000
1056
|
|
1001
|
-
#
|
1057
|
+
# Destroy any remaining subscriptions.
|
1058
|
+
@subs.each do |_, sub|
|
1059
|
+
if sub.wait_for_msgs_t && sub.wait_for_msgs_t.alive?
|
1060
|
+
sub.wait_for_msgs_t.exit
|
1061
|
+
sub.pending_queue.clear
|
1062
|
+
end
|
1063
|
+
end
|
1064
|
+
@subs.clear
|
1065
|
+
|
1002
1066
|
if do_cbs
|
1003
1067
|
@disconnect_cb.call(@last_err) if @disconnect_cb
|
1004
1068
|
@close_cb.call if @close_cb
|
@@ -1195,7 +1259,9 @@ module NATS
|
|
1195
1259
|
class Subscription
|
1196
1260
|
include MonitorMixin
|
1197
1261
|
|
1198
|
-
attr_accessor :subject, :queue, :future, :callback, :response, :received, :max
|
1262
|
+
attr_accessor :subject, :queue, :future, :callback, :response, :received, :max, :pending
|
1263
|
+
attr_accessor :pending_queue, :pending_size, :wait_for_msgs_t, :is_slow_consumer
|
1264
|
+
attr_accessor :pending_msgs_limit, :pending_bytes_limit
|
1199
1265
|
|
1200
1266
|
def initialize
|
1201
1267
|
super # required to initialize monitor
|
@@ -1206,6 +1272,15 @@ module NATS
|
|
1206
1272
|
@response = nil
|
1207
1273
|
@received = 0
|
1208
1274
|
@max = nil
|
1275
|
+
@pending = nil
|
1276
|
+
|
1277
|
+
# State from async subscriber messages delivery
|
1278
|
+
@pending_queue = nil
|
1279
|
+
@pending_size = 0
|
1280
|
+
@pending_msgs_limit = nil
|
1281
|
+
@pending_bytes_limit = nil
|
1282
|
+
@wait_for_msgs_t = nil
|
1283
|
+
@is_slow_consumer = false
|
1209
1284
|
end
|
1210
1285
|
end
|
1211
1286
|
|
data/lib/nats/io/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nats-pure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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: 2018-
|
11
|
+
date: 2018-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: NATS is an open-source, high-performance, lightweight cloud messaging
|
14
14
|
system.
|