nats-pure 2.6.0 → 2.7.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.
@@ -30,6 +30,10 @@ module NATS
30
30
  :republish,
31
31
  :direct,
32
32
  :validate_keys,
33
+ # Compress the bucket's stream with S2 (requires nats-server v2.10.0).
34
+ :compression,
35
+ # Freeform metadata of the bucket (requires nats-server v2.10.0).
36
+ :metadata,
33
37
  keyword_init: true
34
38
  ) do
35
39
  def initialize(opts = {})
@@ -35,6 +35,18 @@ module NATS
35
35
  def ttl
36
36
  @stream_info.config.max_age / ::NATS::NANOSECONDS
37
37
  end
38
+
39
+ # Whether the bucket's stream is compressed (requires nats-server v2.10.0).
40
+ def compressed?
41
+ compression = @stream_info.config.compression
42
+ !compression.nil? && compression != "none"
43
+ end
44
+
45
+ # The bucket's metadata, including the metadata that the server sets
46
+ # (requires nats-server v2.10.0).
47
+ def metadata
48
+ @stream_info.config.metadata
49
+ end
38
50
  end
39
51
  end
40
52
  end
@@ -59,6 +59,10 @@ module NATS
59
59
  raise NATS::KeyValue::KeyHistoryTooLargeError
60
60
  end
61
61
 
62
+ unless [true, false, nil].include?(config.compression)
63
+ raise ArgumentError.new("nats: compression must be true or false")
64
+ end
65
+
62
66
  stream = JetStream::API::StreamConfig.new(
63
67
  name: "KV_#{config.bucket}",
64
68
  description: config.description,
@@ -76,7 +80,9 @@ module NATS
76
80
  max_msgs_per_subject: config.history,
77
81
  num_replicas: config.replicas,
78
82
  storage: config.storage,
79
- republish: config.republish
83
+ republish: config.republish,
84
+ compression: config.compression ? "s2" : nil,
85
+ metadata: config.metadata
80
86
  )
81
87
 
82
88
  si = add_stream(stream)
data/lib/nats/io/kv.rb CHANGED
@@ -258,7 +258,8 @@ module NATS
258
258
  CONSUMER_STALLED_HDR = "Nats-Consumer-Stalled"
259
259
 
260
260
  # watch will be signaled when a key that matches the keys
261
- # pattern is updated.
261
+ # pattern is updated. keys can also be an Array of patterns
262
+ # (requires nats-server v2.10.0); an empty Array watches all keys.
262
263
  # The first update after starting the watch is nil in case
263
264
  # there are no pending updates.
264
265
  def watch(keys, params = {})
@@ -267,7 +268,12 @@ module NATS
267
268
  params[:ignore_deletes] ||= false
268
269
  params[:idle_heartbeat] ||= 5 # seconds
269
270
  params[:inactive_threshold] ||= 5 * 60 # 5 minutes
270
- subject = "#{@pre}#{keys}"
271
+ subject = if keys.is_a?(Array)
272
+ keys = [">"] if keys.empty?
273
+ keys.map { |key| "#{@pre}#{key}" }
274
+ else
275
+ "#{@pre}#{keys}"
276
+ end
271
277
  init_setup = new_cond
272
278
  init_setup_done = false
273
279
  nc = @js.nc
@@ -294,7 +300,7 @@ module NATS
294
300
  }
295
301
 
296
302
  # watch_updates callback.
297
- sub = @js.subscribe(subject, config: ordered) do |msg|
303
+ sub = @js.subscribe(subject, stream: @stream, config: ordered) do |msg|
298
304
  synchronize do
299
305
  if !init_setup_done
300
306
  init_setup.wait(@js.opts[:timeout])
@@ -379,6 +385,9 @@ module NATS
379
385
  begin
380
386
  cinfo = sub.consumer_info
381
387
  stream_name = cinfo.stream_name
388
+ # Snapshot the keys filter too: subscribe set it on the consumer,
389
+ # not on ordered, and a recreated consumer needs it.
390
+ filter = cinfo.config.to_h.slice(:filter_subject, :filter_subjects)
382
391
 
383
392
  synchronize do
384
393
  init_setup_done = true
@@ -417,9 +426,11 @@ module NATS
417
426
  current
418
427
  }
419
428
  if !active
420
- ccreq = ordered.dup
429
+ ccreq = ordered.merge(filter)
421
430
  ccreq[:deliver_policy] = "by_start_sequence"
422
- ccreq[:opt_start_seq] = watcher._sseq
431
+ # Resume after the last entry. With none yet, that is the start of
432
+ # the stream, so earlier revisions of the keys are replayed too.
433
+ ccreq[:opt_start_seq] = watcher._sseq + 1
423
434
  ccreq[:deliver_subject] = deliver_subject
424
435
  ccreq[:idle_heartbeat] = ordered[:idle_heartbeat]
425
436
  ccreq[:inactive_threshold] = ordered[:inactive_threshold]
@@ -89,18 +89,19 @@ module NATS
89
89
  def next_msg(opts = {})
90
90
  timeout = opts[:timeout] ||= 0.5
91
91
  synchronize do
92
- return @pending_queue.pop if !@pending_queue.empty?
92
+ if @pending_queue.empty?
93
+ # Wait for a bit until getting a signal.
94
+ MonotonicTime.with_nats_timeout(timeout) do
95
+ wait_for_msgs_cond.wait(timeout)
96
+ end
93
97
 
94
- # Wait for a bit until getting a signal.
95
- MonotonicTime.with_nats_timeout(timeout) do
96
- wait_for_msgs_cond.wait(timeout)
98
+ raise NATS::Timeout if @pending_queue.empty?
97
99
  end
98
100
 
99
- if !@pending_queue.empty?
100
- return @pending_queue.pop
101
- else
102
- raise NATS::Timeout
103
- end
101
+ # Decrease pending size since consumed already
102
+ msg = @pending_queue.pop
103
+ self.pending_size -= msg.data.size
104
+ msg
104
105
  end
105
106
  end
106
107
 
@@ -17,7 +17,7 @@
17
17
  module NATS
18
18
  module IO
19
19
  # VERSION is the version of the client announced on CONNECT to the server.
20
- VERSION = "2.6.0"
20
+ VERSION = "2.7.0"
21
21
 
22
22
  # LANG is the lang runtime of the client announced on CONNECT to the server.
23
23
  LANG = "#{RUBY_ENGINE}#{RUBY_VERSION}".freeze
@@ -7,18 +7,27 @@ module NATS
7
7
  class SequenceInfo < Struct[Integer]
8
8
  end
9
9
 
10
- class ConsumerInfo < Struct[String | NATS::JetStream::API::ConsumerConfig | NATS::JetStream::API::SequenceInfo | Integer | Hash[Symbol, untyped]]
10
+ class PriorityGroupState < Struct[String | Time]
11
11
  end
12
12
 
13
- class ConsumerConfig < Struct[String | Integer]
13
+ class ConsumerInfo < Struct[String | NATS::JetStream::API::ConsumerConfig | NATS::JetStream::API::SequenceInfo | Integer | Hash[Symbol, untyped] | Time | bool | Array[NATS::JetStream::API::PriorityGroupState]]
14
+ end
15
+
16
+ class ConsumerConfig < Struct[String | Integer | Time | Array[String]]
14
17
  def to_json: (*Hash[untyped, untyped]) -> String
15
18
  end
16
19
 
20
+ class ConsumerPauseResponse < Struct[bool | Time | Integer]
21
+ end
22
+
23
+ class ConsumerResetResponse < Struct[NATS::JetStream::API::ConsumerInfo | Integer]
24
+ end
25
+
17
26
  class StreamConfig < Struct[String | Hash[Symbol, untyped] | NATS::JetStream::API::StreamState | bool | Integer]
18
27
  def to_json: (*Hash[untyped, untyped]) -> String
19
28
  end
20
29
 
21
- class StreamInfo < Struct[String | Hash[Symbol, untyped]]
30
+ class StreamInfo < Struct[String | Hash[Symbol, untyped] | Array[Hash[Symbol, untyped]] | Time]
22
31
  end
23
32
 
24
33
  class StreamState < Struct[Integer]
@@ -49,6 +49,18 @@ module NATS
49
49
 
50
50
  class BadRequest < NATS::JetStream::Error::APIError
51
51
  end
52
+
53
+ class ConsumerAlreadyExists < NATS::JetStream::Error::BadRequest
54
+ end
55
+
56
+ class ConsumerDoesNotExist < NATS::JetStream::Error::BadRequest
57
+ end
58
+
59
+ class ConsumerInvalidReset < NATS::JetStream::Error::BadRequest
60
+ end
61
+
62
+ class PinIdMismatch < NATS::JetStream::Error::APIError
63
+ end
52
64
  end
53
65
  end
54
66
  end
@@ -0,0 +1,33 @@
1
+ module NATS
2
+ class JetStream
3
+ module Header
4
+ MSG_ID: 'Nats-Msg-Id'
5
+ EXPECTED_STREAM: 'Nats-Expected-Stream'
6
+ EXPECTED_LAST_SEQUENCE: 'Nats-Expected-Last-Sequence'
7
+ EXPECTED_LAST_SUBJECT_SEQUENCE: 'Nats-Expected-Last-Subject-Sequence'
8
+ EXPECTED_LAST_SUBJECT_SEQUENCE_SUBJECT: 'Nats-Expected-Last-Subject-Sequence-Subject'
9
+ EXPECTED_LAST_MSG_ID: 'Nats-Expected-Last-Msg-Id'
10
+ ROLLUP: 'Nats-Rollup'
11
+ MSG_TTL: 'Nats-TTL'
12
+ MARKER_REASON: 'Nats-Marker-Reason'
13
+ STREAM: 'Nats-Stream'
14
+ SUBJECT: 'Nats-Subject'
15
+ SEQUENCE: 'Nats-Sequence'
16
+ TIME_STAMP: 'Nats-Time-Stamp'
17
+ LAST_SEQUENCE: 'Nats-Last-Sequence'
18
+ STREAM_SOURCE: 'Nats-Stream-Source'
19
+ BATCH_ID: 'Nats-Batch-Id'
20
+ BATCH_SEQUENCE: 'Nats-Batch-Sequence'
21
+ BATCH_COMMIT: 'Nats-Batch-Commit'
22
+ SCHEDULE: 'Nats-Schedule'
23
+ SCHEDULE_TARGET: 'Nats-Schedule-Target'
24
+ SCHEDULE_SOURCE: 'Nats-Schedule-Source'
25
+ SCHEDULE_TTL: 'Nats-Schedule-TTL'
26
+ SCHEDULE_TIME_ZONE: 'Nats-Schedule-Time-Zone'
27
+ SCHEDULE_ROLLUP: 'Nats-Schedule-Rollup'
28
+ SCHEDULER: 'Nats-Scheduler'
29
+ SCHEDULE_NEXT: 'Nats-Schedule-Next'
30
+ REQUIRED_API_LEVEL: 'Nats-Required-Api-Level'
31
+ end
32
+ end
33
+ end
@@ -11,6 +11,7 @@ module NATS
11
11
  ExpectedLastMsgID: 'Nats-Expected-Last-Msg-Id'
12
12
  LastConsumerSeq: 'Nats-Last-Consumer'
13
13
  LastStreamSeq: 'Nats-Last-Stream'
14
+ PinId: 'Nats-Pin-Id'
14
15
  end
15
16
  end
16
17
  end
@@ -6,6 +6,7 @@ module NATS
6
6
  NoMsgs: '404'
7
7
  NotFound: '404'
8
8
  RequestTimeout: '408'
9
+ PinIdMismatch: '423'
9
10
  ServiceUnavailable: '503'
10
11
  end
11
12
  end
@@ -6,11 +6,13 @@ module NATS
6
6
  # class << self
7
7
  def self.next_req_to_json: (Hash[Symbol, untyped]) -> String
8
8
 
9
+ def self.parse_time: (String?) -> Time?
10
+
9
11
  def self.is_status_msg: (NATS::Msg) -> bool
10
12
 
11
13
  def self.check_503_error: (NATS::Msg) -> void
12
14
 
13
- def self.from_msg: (NATS::Msg) -> NATS::JetStream::API::Error
15
+ def self.from_msg: (NATS::Msg) -> (NATS::JetStream::API::Error | NATS::JetStream::Error::PinIdMismatch)
14
16
 
15
17
  def self.from_error: (Hash[Symbol, untyped]) -> (
16
18
  NATS::JetStream::Error::ServiceUnavailable |
@@ -9,12 +9,24 @@ module NATS
9
9
 
10
10
  def delete_stream: (String, ?Hash[Symbol, untyped]) -> bool
11
11
 
12
- def add_consumer: (String, JetStream::API::ConsumerConfig, ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerInfo
12
+ def add_consumer: (String, JetStream::API::ConsumerConfig | Hash[Symbol, untyped], ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerInfo
13
+
14
+ def create_consumer: (String, JetStream::API::ConsumerConfig | Hash[Symbol, untyped], ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerInfo
15
+
16
+ def update_consumer: (String, JetStream::API::ConsumerConfig | Hash[Symbol, untyped], ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerInfo
13
17
 
14
18
  def consumer_info: (String, String, ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerInfo
15
19
 
16
20
  def delete_consumer: (String, String, ?Hash[Symbol, untyped]) -> bool
17
21
 
22
+ def pause_consumer: (String, String, Time | String, ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerPauseResponse
23
+
24
+ def resume_consumer: (String, String, ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerPauseResponse
25
+
26
+ def unpin_consumer: (String, String, String, ?Hash[Symbol, untyped]) -> bool
27
+
28
+ def reset_consumer: (String, String, ?Hash[Symbol, untyped]) -> JetStream::API::ConsumerResetResponse
29
+
18
30
  def find_stream_name_by_subject: (String, ?Hash[Symbol, untyped]) -> String
19
31
 
20
32
  def get_msg: (String, ?Hash[Symbol, untyped]) -> JetStream::API::RawStreamMsg
@@ -25,9 +37,17 @@ module NATS
25
37
 
26
38
  private
27
39
 
40
+ def upsert_consumer: (String, JetStream::API::ConsumerConfig | Hash[Symbol, untyped], String?, Hash[Symbol, untyped]) -> JetStream::API::ConsumerInfo
41
+
42
+ def request_pause: (String, String, Hash[Symbol, String], Hash[Symbol, untyped]) -> JetStream::API::ConsumerPauseResponse
43
+
44
+ def rfc3339: (Time | String | nil) -> String?
45
+
28
46
  def api_request: (String, String, ?Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
29
47
 
30
48
  def _lift_msg_to_raw_msg: (NATS::Msg) -> JetStream::API::RawStreamMsg
49
+
50
+ def stream_config_json: (JetStream::API::StreamConfig) -> String
31
51
  end
32
52
  end
33
53
  end
@@ -4,11 +4,49 @@ module NATS
4
4
  class PubAck < Struct[String | Numeric | bool]
5
5
  end
6
6
 
7
+ UNCHECKED_PULL_AGE: Integer
8
+
9
+ def self.extended: (NATS::Subscription) -> void
10
+
7
11
  def next_msg: (untyped) -> void
8
12
 
9
- def fetch: (Integer, Hash[Symbol, untyped]) -> Array[NATS::Msg]
13
+ def fetch: (Integer, Hash[Symbol, untyped]) ?{ (NATS::Msg) -> void } -> Array[NATS::Msg]
10
14
 
11
15
  def consumer_info: (Hash[Symbol, untyped]) -> NATS::JetStream::ConsumerInfo
16
+
17
+ private
18
+
19
+ def pull_and_wait: (Array[NATS::Msg], Hash[Symbol, untyped], Float) ?{ (NATS::Msg) -> void } -> bool
20
+
21
+ def pull_pending: (Array[NATS::Msg], Hash[Symbol, untyped], Float) ?{ (NATS::Msg) -> void } -> bool
22
+
23
+ def receive: (Array[NATS::Msg], Integer, String?, ^() -> NATS::Msg?) ?{ (NATS::Msg) -> void } -> bool
24
+
25
+ def release: (NATS::Subscription, Float) -> void
26
+
27
+ def hand_over: (NATS::Subscription, ?Float) -> void
28
+
29
+ def keep: (NATS::Msg) -> void
30
+
31
+ def collect: (Array[NATS::Msg], NATS::Msg) ?{ (NATS::Msg) -> void } -> void
32
+
33
+ def pull_ended?: (NATS::Msg) -> bool
34
+
35
+ def pull_expires: (Float) -> Integer
36
+
37
+ def wait_pending: (String, Float) -> NATS::Msg?
38
+
39
+ def next_pending: (?String?) -> NATS::Msg?
40
+
41
+ def next_reply: (NATS::Subscription, Float) -> NATS::Msg?
42
+
43
+ def pull: (Hash[Symbol, untyped], String) -> String?
44
+
45
+ def pop_pending: () -> NATS::Msg?
46
+
47
+ def track_pin: (NATS::Msg) -> NATS::Msg
48
+
49
+ def forget_pin: (String?) -> void
12
50
  end
13
51
  end
14
- end
52
+ end
@@ -6,10 +6,18 @@ module NATS
6
6
  class PubAck < Struct[String | Numeric | bool]
7
7
  end
8
8
 
9
- def publish: (String, String, Hash[Symbol, untyped]) -> NATS::JetStream::PubAck
9
+ def publish: (String, ?String, **untyped) -> NATS::JetStream::PubAck
10
10
 
11
11
  def subscribe: (String, Hash[Symbol, untyped]) { (?(NATS::Msg | String), ?String, ?String, ?Hash[Symbol, untyped]) -> void } -> NATS::JetStream::PushSubscription
12
12
 
13
13
  def pull_subscribe: (String, String, Hash[Symbol, untyped]) -> NATS::JetStream::PullSubscription
14
+
15
+ private
16
+
17
+ def msg_ttl: (Integer | :never) -> String
18
+
19
+ def schedule_header: (target: String, ?at: Time?, ?every: Integer?, ?cron: String?, ?source: String?, ?ttl: (Integer | :never)?, ?time_zone: String?, ?rollup: bool?) -> Hash[String, String]
20
+
21
+ def nonempty_string?: (untyped) -> bool
14
22
  end
15
23
  end
@@ -12,6 +12,10 @@ module NATS
12
12
  def history: () -> Integer
13
13
 
14
14
  def ttl: () -> Float
15
+
16
+ def compressed?: () -> bool
17
+
18
+ def metadata: () -> Hash[Symbol, String]?
15
19
  end
16
20
  end
17
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nats-pure
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Waldemar Quevedo
@@ -196,6 +196,7 @@ files:
196
196
  - lib/nats/io/jetstream.rb
197
197
  - lib/nats/io/jetstream/api.rb
198
198
  - lib/nats/io/jetstream/errors.rb
199
+ - lib/nats/io/jetstream/header.rb
199
200
  - lib/nats/io/jetstream/js.rb
200
201
  - lib/nats/io/jetstream/js/config.rb
201
202
  - lib/nats/io/jetstream/js/header.rb
@@ -235,6 +236,7 @@ files:
235
236
  - sig/nats/io/jetstream.rbs
236
237
  - sig/nats/io/jetstream/api.rbs
237
238
  - sig/nats/io/jetstream/errors.rbs
239
+ - sig/nats/io/jetstream/header.rbs
238
240
  - sig/nats/io/jetstream/js.rbs
239
241
  - sig/nats/io/jetstream/js/config.rbs
240
242
  - sig/nats/io/jetstream/js/header.rbs