nats-pure 0.3.0 → 0.4.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/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.
|