nats-pure 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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 -3
  5. data/lib/nats/io/client.rb +303 -280
  6. data/lib/nats/io/errors.rb +2 -0
  7. data/lib/nats/io/jetstream/api.rb +53 -50
  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 +103 -101
  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 +102 -106
  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,32 +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
-
123
- # NATS v2.10 features
124
- :metadata, :filter_subjects, :max_bytes,
125
- keyword_init: true) do
126
- 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 = {})
127
129
  # Filter unrecognized fields just in case.
128
130
  rem = opts.keys - members
129
131
  opts.delete_if { |k| rem.include?(k) }
130
- super(opts)
132
+ super
131
133
  end
132
134
  end
133
135
 
@@ -196,12 +198,13 @@ module NATS
196
198
  :allow_direct,
197
199
  :mirror_direct,
198
200
  :metadata,
199
- keyword_init: true) do
200
- def initialize(opts={})
201
+ keyword_init: true
202
+ ) do
203
+ def initialize(opts = {})
201
204
  # Filter unrecognized fields just in case.
202
205
  rem = opts.keys - members
203
206
  opts.delete_if { |k| rem.include?(k) }
204
- super(opts)
207
+ super
205
208
  end
206
209
  end
207
210
 
@@ -218,8 +221,8 @@ module NATS
218
221
  # @!attribute domain
219
222
  # @return [String]
220
223
  StreamInfo = Struct.new(:type, :config, :created, :state, :domain,
221
- keyword_init: true) do
222
- def initialize(opts={})
224
+ keyword_init: true) do
225
+ def initialize(opts = {})
223
226
  opts[:config] = StreamConfig.new(opts[:config])
224
227
  opts[:state] = StreamState.new(opts[:state])
225
228
  opts[:created] = ::Time.parse(opts[:created])
@@ -227,7 +230,7 @@ module NATS
227
230
  # Filter fields and freeze.
228
231
  rem = opts.keys - members
229
232
  opts.delete_if { |k| rem.include?(k) }
230
- super(opts)
233
+ super
231
234
  freeze
232
235
  end
233
236
  end
@@ -245,12 +248,12 @@ module NATS
245
248
  # @!attribute consumer_count
246
249
  # @return [Integer]
247
250
  StreamState = Struct.new(:messages, :bytes, :first_seq, :first_ts,
248
- :last_seq, :last_ts, :consumer_count,
249
- keyword_init: true) do
250
- def initialize(opts={})
251
+ :last_seq, :last_ts, :consumer_count,
252
+ keyword_init: true) do
253
+ def initialize(opts = {})
251
254
  rem = opts.keys - members
252
255
  opts.delete_if { |k| rem.include?(k) }
253
- super(opts)
256
+ super
254
257
  end
255
258
  end
256
259
 
@@ -267,13 +270,13 @@ module NATS
267
270
  # @!attribute did_create
268
271
  # @return [Boolean]
269
272
  StreamCreateResponse = Struct.new(:type, :config, :created, :state, :did_create,
270
- keyword_init: true) do
271
- def initialize(opts={})
273
+ keyword_init: true) do
274
+ def initialize(opts = {})
272
275
  rem = opts.keys - members
273
276
  opts.delete_if { |k| rem.include?(k) }
274
277
  opts[:config] = StreamConfig.new(opts[:config])
275
278
  opts[:state] = StreamState.new(opts[:state])
276
- super(opts)
279
+ super
277
280
  freeze
278
281
  end
279
282
  end
@@ -297,11 +300,11 @@ module NATS
297
300
  # Filter out members not present.
298
301
  rem = opts.keys - members
299
302
  opts.delete_if { |k| rem.include?(k) }
300
- super(opts)
303
+ super
301
304
  end
302
305
 
303
306
  def sequence
304
- self.seq
307
+ seq
305
308
  end
306
309
  end
307
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