nats-pure 2.3.0 → 2.5.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/README.md +10 -3
  4. data/lib/nats/client.rb +7 -2
  5. data/lib/nats/io/client.rb +304 -282
  6. data/lib/nats/io/errors.rb +2 -0
  7. data/lib/nats/io/jetstream/api.rb +54 -47
  8. data/lib/nats/io/jetstream/errors.rb +30 -14
  9. data/lib/nats/io/jetstream/js/config.rb +9 -3
  10. data/lib/nats/io/jetstream/js/header.rb +15 -9
  11. data/lib/nats/io/jetstream/js/status.rb +11 -5
  12. data/lib/nats/io/jetstream/js/sub.rb +4 -2
  13. data/lib/nats/io/jetstream/js.rb +10 -8
  14. data/lib/nats/io/jetstream/manager.rb +104 -83
  15. data/lib/nats/io/jetstream/msg/ack.rb +15 -9
  16. data/lib/nats/io/jetstream/msg/ack_methods.rb +24 -22
  17. data/lib/nats/io/jetstream/msg/metadata.rb +9 -7
  18. data/lib/nats/io/jetstream/msg.rb +11 -4
  19. data/lib/nats/io/jetstream/pull_subscription.rb +21 -10
  20. data/lib/nats/io/jetstream/push_subscription.rb +3 -1
  21. data/lib/nats/io/jetstream.rb +125 -54
  22. data/lib/nats/io/kv/api.rb +7 -3
  23. data/lib/nats/io/kv/bucket_status.rb +7 -5
  24. data/lib/nats/io/kv/errors.rb +25 -2
  25. data/lib/nats/io/kv/manager.rb +19 -10
  26. data/lib/nats/io/kv.rb +359 -22
  27. data/lib/nats/io/msg.rb +19 -19
  28. data/lib/nats/io/parser.rb +23 -23
  29. data/lib/nats/io/rails.rb +2 -0
  30. data/lib/nats/io/subscription.rb +25 -22
  31. data/lib/nats/io/version.rb +4 -2
  32. data/lib/nats/io/websocket.rb +10 -8
  33. data/lib/nats/nuid.rb +33 -22
  34. data/lib/nats/service/callbacks.rb +22 -0
  35. data/lib/nats/service/endpoint.rb +155 -0
  36. data/lib/nats/service/errors.rb +44 -0
  37. data/lib/nats/service/group.rb +37 -0
  38. data/lib/nats/service/monitoring.rb +108 -0
  39. data/lib/nats/service/stats.rb +52 -0
  40. data/lib/nats/service/status.rb +66 -0
  41. data/lib/nats/service/validator.rb +31 -0
  42. data/lib/nats/service.rb +121 -0
  43. data/lib/nats/utils/list.rb +26 -0
  44. data/lib/nats-pure.rb +5 -0
  45. data/lib/nats.rb +10 -6
  46. metadata +176 -5
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -12,9 +14,9 @@
12
14
  # limitations under the License.
13
15
  #
14
16
 
15
- require_relative 'errors'
16
- require 'base64'
17
- require 'time'
17
+ require_relative "errors"
18
+ require "base64"
19
+ require "time"
18
20
 
19
21
  module NATS
20
22
  class JetStream
@@ -29,12 +31,12 @@ module NATS
29
31
  # @!attribute stream_seq
30
32
  # @return [Integer] The stream sequence.
31
33
  SequenceInfo = Struct.new(:consumer_seq, :stream_seq, :last_active,
32
- keyword_init: true) do
33
- def initialize(opts={})
34
+ keyword_init: true) do
35
+ def initialize(opts = {})
34
36
  # Filter unrecognized fields and freeze.
35
37
  rem = opts.keys - members
36
38
  opts.delete_if { |k| rem.include?(k) }
37
- super(opts)
39
+ super
38
40
  freeze
39
41
  end
40
42
  end
@@ -64,21 +66,23 @@ module NATS
64
66
  # @!attribute cluster
65
67
  # @return [Hash]
66
68
  ConsumerInfo = Struct.new(:type, :stream_name, :name, :created,
67
- :config, :delivered, :ack_floor,
68
- :num_ack_pending, :num_redelivered, :num_waiting,
69
- :num_pending, :cluster, :push_bound,
70
- keyword_init: true) do
71
- def initialize(opts={})
69
+ :config, :delivered, :ack_floor,
70
+ :num_ack_pending, :num_redelivered, :num_waiting,
71
+ :num_pending, :cluster, :push_bound,
72
+ keyword_init: true) do
73
+ def initialize(opts = {})
72
74
  opts[:created] = Time.parse(opts[:created])
73
75
  opts[:ack_floor] = SequenceInfo.new(opts[:ack_floor])
74
76
  opts[:delivered] = SequenceInfo.new(opts[:delivered])
75
77
  opts[:config][:ack_wait] = opts[:config][:ack_wait] / ::NATS::NANOSECONDS
78
+ opts[:config][:inactive_threshold] = opts[:config][:inactive_threshold] / ::NATS::NANOSECONDS if opts[:config][:inactive_threshold]
79
+ opts[:config][:idle_heartbeat] = opts[:config][:idle_heartbeat] / ::NATS::NANOSECONDS if opts[:config][:idle_heartbeat]
76
80
  opts[:config] = ConsumerConfig.new(opts[:config])
77
81
  opts.delete(:cluster)
78
82
  # Filter unrecognized fields just in case.
79
83
  rem = opts.keys - members
80
84
  opts.delete_if { |k| rem.include?(k) }
81
- super(opts)
85
+ super
82
86
  freeze
83
87
  end
84
88
  end
@@ -102,29 +106,30 @@ module NATS
102
106
  # @!attribute max_ack_pending
103
107
  # @return [Integer]
104
108
  ConsumerConfig = Struct.new(:name, :durable_name, :description,
105
- :deliver_policy, :opt_start_seq, :opt_start_time,
106
- :ack_policy, :ack_wait, :max_deliver, :backoff,
107
- :filter_subject, :replay_policy, :rate_limit_bps,
108
- :sample_freq, :max_waiting, :max_ack_pending,
109
- :flow_control, :idle_heartbeat, :headers_only,
110
-
111
- # Pull based options
112
- :max_batch, :max_expires,
113
- # Push based consumers
114
- :deliver_subject, :deliver_group,
115
- # Ephemeral inactivity threshold
116
- :inactive_threshold,
117
- # Generally inherited by parent stream and other markers,
118
- # now can be configured directly.
119
- :num_replicas,
120
- # Force memory storage
121
- :mem_storage,
122
- keyword_init: true) do
123
- def initialize(opts={})
109
+ :deliver_policy, :opt_start_seq, :opt_start_time,
110
+ :ack_policy, :ack_wait, :max_deliver, :backoff,
111
+ :filter_subject, :replay_policy, :rate_limit_bps,
112
+ :sample_freq, :max_waiting, :max_ack_pending,
113
+ :flow_control, :idle_heartbeat, :headers_only,
114
+ # Pull based options
115
+ :max_batch, :max_expires,
116
+ # Push based consumers
117
+ :deliver_subject, :deliver_group,
118
+ # Ephemeral inactivity threshold
119
+ :inactive_threshold,
120
+ # Generally inherited by parent stream and other markers,
121
+ # now can be configured directly.
122
+ :num_replicas,
123
+ # Force memory storage
124
+ :mem_storage,
125
+ # NATS v2.10 features
126
+ :metadata, :filter_subjects, :max_bytes,
127
+ keyword_init: true) do
128
+ def initialize(opts = {})
124
129
  # Filter unrecognized fields just in case.
125
130
  rem = opts.keys - members
126
131
  opts.delete_if { |k| rem.include?(k) }
127
- super(opts)
132
+ super
128
133
  end
129
134
  end
130
135
 
@@ -192,12 +197,14 @@ module NATS
192
197
  :republish,
193
198
  :allow_direct,
194
199
  :mirror_direct,
195
- keyword_init: true) do
196
- def initialize(opts={})
200
+ :metadata,
201
+ keyword_init: true
202
+ ) do
203
+ def initialize(opts = {})
197
204
  # Filter unrecognized fields just in case.
198
205
  rem = opts.keys - members
199
206
  opts.delete_if { |k| rem.include?(k) }
200
- super(opts)
207
+ super
201
208
  end
202
209
  end
203
210
 
@@ -214,8 +221,8 @@ module NATS
214
221
  # @!attribute domain
215
222
  # @return [String]
216
223
  StreamInfo = Struct.new(:type, :config, :created, :state, :domain,
217
- keyword_init: true) do
218
- def initialize(opts={})
224
+ keyword_init: true) do
225
+ def initialize(opts = {})
219
226
  opts[:config] = StreamConfig.new(opts[:config])
220
227
  opts[:state] = StreamState.new(opts[:state])
221
228
  opts[:created] = ::Time.parse(opts[:created])
@@ -223,7 +230,7 @@ module NATS
223
230
  # Filter fields and freeze.
224
231
  rem = opts.keys - members
225
232
  opts.delete_if { |k| rem.include?(k) }
226
- super(opts)
233
+ super
227
234
  freeze
228
235
  end
229
236
  end
@@ -241,12 +248,12 @@ module NATS
241
248
  # @!attribute consumer_count
242
249
  # @return [Integer]
243
250
  StreamState = Struct.new(:messages, :bytes, :first_seq, :first_ts,
244
- :last_seq, :last_ts, :consumer_count,
245
- keyword_init: true) do
246
- def initialize(opts={})
251
+ :last_seq, :last_ts, :consumer_count,
252
+ keyword_init: true) do
253
+ def initialize(opts = {})
247
254
  rem = opts.keys - members
248
255
  opts.delete_if { |k| rem.include?(k) }
249
- super(opts)
256
+ super
250
257
  end
251
258
  end
252
259
 
@@ -263,13 +270,13 @@ module NATS
263
270
  # @!attribute did_create
264
271
  # @return [Boolean]
265
272
  StreamCreateResponse = Struct.new(:type, :config, :created, :state, :did_create,
266
- keyword_init: true) do
267
- def initialize(opts={})
273
+ keyword_init: true) do
274
+ def initialize(opts = {})
268
275
  rem = opts.keys - members
269
276
  opts.delete_if { |k| rem.include?(k) }
270
277
  opts[:config] = StreamConfig.new(opts[:config])
271
278
  opts[:state] = StreamState.new(opts[:state])
272
- super(opts)
279
+ super
273
280
  freeze
274
281
  end
275
282
  end
@@ -293,11 +300,11 @@ module NATS
293
300
  # Filter out members not present.
294
301
  rem = opts.keys - members
295
302
  opts.delete_if { |k| rem.include?(k) }
296
- super(opts)
303
+ super
297
304
  end
298
305
 
299
306
  def sequence
300
- self.seq
307
+ seq
301
308
  end
302
309
  end
303
310
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -16,7 +18,6 @@ module NATS
16
18
  class JetStream
17
19
  # Error is any error that may arise when interacting with JetStream.
18
20
  class Error < NATS::IO::Error
19
-
20
21
  # When there is a NATS::IO::NoResponders error after making a publish request.
21
22
  class NoStreamResponse < Error; end
22
23
 
@@ -41,18 +42,25 @@ module NATS
41
42
 
42
43
  # When the server responds with an error from the JetStream API.
43
44
  class APIError < Error
44
- attr_reader :code, :err_code, :description, :stream, :seq
45
+ attr_accessor :code, :err_code, :description, :stream, :consumer, :seq
45
46
 
46
- def initialize(params={})
47
+ def initialize(params = {})
47
48
  @code = params[:code]
48
49
  @err_code = params[:err_code]
49
50
  @description = params[:description]
50
51
  @stream = params[:stream]
52
+ @consumer = params[:consumer]
51
53
  @seq = params[:seq]
52
54
  end
53
55
 
54
56
  def to_s
55
- "#{@description} (status_code=#{@code}, err_code=#{@err_code})"
57
+ if @stream && @consumer
58
+ "#{@description} (status_code=#{@code}, err_code=#{@err_code}, stream=#{@stream}, consumer=#{@consumer})"
59
+ elsif @stream
60
+ "#{@description} (status_code=#{@code}, err_code=#{@err_code}, stream=#{@stream})"
61
+ else
62
+ "#{@description} (status_code=#{@code}, err_code=#{@err_code})"
63
+ end
56
64
  end
57
65
  end
58
66
 
@@ -61,8 +69,8 @@ module NATS
61
69
  # running in cluster mode.
62
70
  # This condition is represented with a message that has 503 status code header.
63
71
  class ServiceUnavailable < APIError
64
- def initialize(params={})
65
- super(params)
72
+ def initialize(params = {})
73
+ super
66
74
  @code ||= 503
67
75
  end
68
76
  end
@@ -70,8 +78,8 @@ module NATS
70
78
  # When there is a hard failure in the JetStream.
71
79
  # This condition is represented with a message that has 500 status code header.
72
80
  class ServerError < APIError
73
- def initialize(params={})
74
- super(params)
81
+ def initialize(params = {})
82
+ super
75
83
  @code ||= 500
76
84
  end
77
85
  end
@@ -79,23 +87,31 @@ module NATS
79
87
  # When a JetStream object was not found.
80
88
  # This condition is represented with a message that has 404 status code header.
81
89
  class NotFound < APIError
82
- def initialize(params={})
83
- super(params)
90
+ def initialize(params = {})
91
+ super
84
92
  @code ||= 404
85
93
  end
86
94
  end
87
95
 
88
96
  # When the stream is not found.
89
- class StreamNotFound < NotFound; end
97
+ class StreamNotFound < NotFound
98
+ def initialize(params = {})
99
+ super
100
+ end
101
+ end
90
102
 
91
103
  # When the consumer or durable is not found by name.
92
- class ConsumerNotFound < NotFound; end
104
+ class ConsumerNotFound < NotFound
105
+ def initialize(params = {})
106
+ super
107
+ end
108
+ end
93
109
 
94
110
  # When the JetStream client makes an invalid request.
95
111
  # This condition is represented with a message that has 400 status code header.
96
112
  class BadRequest < APIError
97
- def initialize(params={})
98
- super(params)
113
+ def initialize(params = {})
114
+ super
99
115
  @code ||= 400
100
116
  end
101
117
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -16,10 +18,14 @@ module NATS
16
18
  class JetStream
17
19
  module JS
18
20
  module Config
21
+ # rubocop:disable Naming/ConstantName
22
+
19
23
  # AckPolicy
20
- AckExplicit = ("explicit".freeze)
21
- AckAll = ("all".freeze)
22
- AckNone = ("none".freeze)
24
+ AckExplicit = "explicit"
25
+ AckAll = "all"
26
+ AckNone = "none"
27
+
28
+ # rubocop:enable Naming/ConstantName
23
29
  end
24
30
  end
25
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -16,15 +18,19 @@ module NATS
16
18
  class JetStream
17
19
  module JS
18
20
  module Header
19
- Status = ("Status".freeze)
20
- Desc = ("Description".freeze)
21
- MsgID = ("Nats-Msg-Id".freeze)
22
- ExpectedStream = ("Nats-Expected-Stream".freeze)
23
- ExpectedLastSeq = ("Nats-Expected-Last-Sequence".freeze)
24
- ExpectedLastSubjSeq = ("Nats-Expected-Last-Subject-Sequence".freeze)
25
- ExpectedLastMsgID = ("Nats-Expected-Last-Msg-Id".freeze)
26
- LastConsumerSeq = ("Nats-Last-Consumer".freeze)
27
- LastStreamSeq = ("Nats-Last-Stream".freeze)
21
+ # rubocop:disable Naming/ConstantName
22
+
23
+ Status = "Status"
24
+ Desc = "Description"
25
+ MsgID = "Nats-Msg-Id"
26
+ ExpectedStream = "Nats-Expected-Stream"
27
+ ExpectedLastSeq = "Nats-Expected-Last-Sequence"
28
+ ExpectedLastSubjSeq = "Nats-Expected-Last-Subject-Sequence"
29
+ ExpectedLastMsgID = "Nats-Expected-Last-Msg-Id"
30
+ LastConsumerSeq = "Nats-Last-Consumer"
31
+ LastStreamSeq = "Nats-Last-Stream"
32
+
33
+ # rubocop:enable Naming/ConstantName
28
34
  end
29
35
  end
30
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -16,11 +18,15 @@ module NATS
16
18
  class JetStream
17
19
  module JS
18
20
  module Status
19
- CtrlMsg = ("100".freeze)
20
- NoMsgs = ("404".freeze)
21
- NotFound = ("404".freeze)
22
- RequestTimeout = ("408".freeze)
23
- ServiceUnavailable = ("503".freeze)
21
+ # rubocop:disable Naming/ConstantName
22
+
23
+ CtrlMsg = "100"
24
+ NoMsgs = "404"
25
+ NotFound = "404"
26
+ RequestTimeout = "408"
27
+ ServiceUnavailable = "503"
28
+
29
+ # rubocop:enable Naming/ConstantName
24
30
  end
25
31
  end
26
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -16,9 +18,9 @@ module NATS
16
18
  class JetStream
17
19
  module JS
18
20
  class Sub
19
- attr_reader :js, :stream, :consumer, :nms
21
+ attr_accessor :js, :stream, :consumer, :nms
20
22
 
21
- def initialize(opts={})
23
+ def initialize(opts = {})
22
24
  @js = opts[:js]
23
25
  @stream = opts[:stream]
24
26
  @consumer = opts[:consumer]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2021 The NATS Authors
2
4
  # Licensed under the Apache License, Version 2.0 (the "License");
3
5
  # you may not use this file except in compliance with the License.
@@ -12,17 +14,17 @@
12
14
  # limitations under the License.
13
15
  #
14
16
 
15
- require_relative 'js/config'
16
- require_relative 'js/header'
17
- require_relative 'js/status'
18
- require_relative 'js/sub'
17
+ require_relative "js/config"
18
+ require_relative "js/header"
19
+ require_relative "js/status"
20
+ require_relative "js/sub"
19
21
 
20
22
  module NATS
21
23
  class JetStream
22
24
  # Misc internal functions to support JS API.
23
25
  # @private
24
26
  module JS
25
- DefaultAPIPrefix = ("$JS.API".freeze)
27
+ DefaultAPIPrefix = "$JS.API" # rubocop:disable Naming/ConstantName
26
28
 
27
29
  class << self
28
30
  def next_req_to_json(next_req)
@@ -34,14 +36,14 @@ module NATS
34
36
  end
35
37
 
36
38
  def is_status_msg(msg)
37
- return (!msg.nil? and (!msg.header.nil? and msg.header[Header::Status]))
39
+ (!msg.nil? and (!msg.header.nil? and msg.header[Header::Status]))
38
40
  end
39
41
 
40
42
  # check_503_error raises exception when a NATS::Msg has a 503 status header.
41
43
  # @param msg [NATS::Msg] The message with status headers.
42
44
  # @raise [NATS::JetStream::Error::ServiceUnavailable]
43
45
  def check_503_error(msg)
44
- return if msg.nil? or msg.header.nil?
46
+ return if msg.nil? || msg.header.nil?
45
47
  if msg.header[Header::Status] == Status::ServiceUnavailable
46
48
  raise ::NATS::JetStream::Error::ServiceUnavailable
47
49
  end
@@ -59,7 +61,7 @@ module NATS
59
61
  check_503_error(msg)
60
62
  code = msg.header[JS::Header::Status]
61
63
  desc = msg.header[JS::Header::Desc]
62
- return ::NATS::JetStream::API::Error.new({code: code, description: desc})
64
+ ::NATS::JetStream::API::Error.new({code: code, description: desc})
63
65
  end
64
66
 
65
67
  # from_error takes an API response that errored and maps the error