nats-pure 2.2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1d8302826b885f0c3a173530bd3d504b5e7a4eb7ec684ac3b43b1ee8f9cf4e3
4
- data.tar.gz: 04aa8801b7ddf434155d1ebf40b03fdd6b89bfc6f95d968ff4a501684081ca02
3
+ metadata.gz: 21e90ec654ece66516fdfac7d16036695ea1afae5f76143e087c8f11564b2135
4
+ data.tar.gz: 3c7644d2bb03f0a9b8fbc982e88a0ea1119d49ed79b849611209755e8b641437
5
5
  SHA512:
6
- metadata.gz: a98b75d47e4b8256c05d284324399807e0bbaf210f2970856b106b46a1264cc12bd96cb00516cb007fd9c68cab001bf08516aee1db46718552bd7397cf8ccb2f
7
- data.tar.gz: b752276fa498c423ecdd0002e530639514ef39a1f5c93e73606c6a6f0351cf275817e13c0339d880fadef9e956fdf7b1f63cc816ff0cd2a2e254db73e071344c
6
+ metadata.gz: 06da3807dd934cd955a4dad34a44927b8885e99b5fe43a641ca7e95ddb8231132f837012d4052d3abac84c025bcc05941c8a2277ed224433f8fab16d7cd4c18e
7
+ data.tar.gz: 12608f0a54fb270de3bda898e4ce2831c166b60b525717de450827e1840e15a5b2b9dd4cf80676490350effc48eb79a31656c46b4eed0af6cd21b264fb03deda
@@ -17,7 +17,7 @@ require_relative 'version'
17
17
  require_relative 'errors'
18
18
  require_relative 'msg'
19
19
  require_relative 'subscription'
20
- require_relative 'js'
20
+ require_relative 'jetstream'
21
21
 
22
22
  require 'nats/nuid'
23
23
  require 'thread'
@@ -854,14 +854,18 @@ module NATS
854
854
  hdr = {}
855
855
  lines = header.lines
856
856
 
857
- # Check if it is an inline status and description.
858
- if lines.count <= 2
857
+ # Check if the first line has an inline status and description.
858
+ if lines.count > 0
859
859
  status_hdr = lines.first.rstrip
860
- hdr[STATUS_HDR] = status_hdr.slice(NATS_HDR_LINE_SIZE-1, STATUS_MSG_LEN)
860
+ status = status_hdr.slice(NATS_HDR_LINE_SIZE-1, STATUS_MSG_LEN)
861
861
 
862
- if NATS_HDR_LINE_SIZE+2 < status_hdr.bytesize
863
- desc = status_hdr.slice(NATS_HDR_LINE_SIZE+STATUS_MSG_LEN, status_hdr.bytesize)
864
- hdr[DESC_HDR] = desc unless desc.empty?
862
+ if status and !status.empty?
863
+ hdr[STATUS_HDR] = status
864
+
865
+ if NATS_HDR_LINE_SIZE+2 < status_hdr.bytesize
866
+ desc = status_hdr.slice(NATS_HDR_LINE_SIZE+STATUS_MSG_LEN, status_hdr.bytesize)
867
+ hdr[DESC_HDR] = desc unless desc.empty?
868
+ end
865
869
  end
866
870
  end
867
871
  begin
@@ -0,0 +1,305 @@
1
+ # Copyright 2021 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ require_relative 'errors'
16
+ require 'base64'
17
+ require 'time'
18
+
19
+ module NATS
20
+ class JetStream
21
+ # JetStream::API are the types used to interact with the JetStream API.
22
+ module API
23
+ # When the server responds with an error from the JetStream API.
24
+ Error = ::NATS::JetStream::Error::APIError
25
+
26
+ # SequenceInfo is a pair of consumer and stream sequence and last activity.
27
+ # @!attribute consumer_seq
28
+ # @return [Integer] The consumer sequence.
29
+ # @!attribute stream_seq
30
+ # @return [Integer] The stream sequence.
31
+ SequenceInfo = Struct.new(:consumer_seq, :stream_seq, :last_active,
32
+ keyword_init: true) do
33
+ def initialize(opts={})
34
+ # Filter unrecognized fields and freeze.
35
+ rem = opts.keys - members
36
+ opts.delete_if { |k| rem.include?(k) }
37
+ super(opts)
38
+ freeze
39
+ end
40
+ end
41
+
42
+ # ConsumerInfo is the current status of a JetStream consumer.
43
+ #
44
+ # @!attribute stream_name
45
+ # @return [String] name of the stream to which the consumer belongs.
46
+ # @!attribute name
47
+ # @return [String] name of the consumer.
48
+ # @!attribute created
49
+ # @return [String] time when the consumer was created.
50
+ # @!attribute config
51
+ # @return [ConsumerConfig] consumer configuration.
52
+ # @!attribute delivered
53
+ # @return [SequenceInfo]
54
+ # @!attribute ack_floor
55
+ # @return [SequenceInfo]
56
+ # @!attribute num_ack_pending
57
+ # @return [Integer]
58
+ # @!attribute num_redelivered
59
+ # @return [Integer]
60
+ # @!attribute num_waiting
61
+ # @return [Integer]
62
+ # @!attribute num_pending
63
+ # @return [Integer]
64
+ # @!attribute cluster
65
+ # @return [Hash]
66
+ 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={})
72
+ opts[:created] = Time.parse(opts[:created])
73
+ opts[:ack_floor] = SequenceInfo.new(opts[:ack_floor])
74
+ opts[:delivered] = SequenceInfo.new(opts[:delivered])
75
+ opts[:config][:ack_wait] = opts[:config][:ack_wait] / ::NATS::NANOSECONDS
76
+ opts[:config] = ConsumerConfig.new(opts[:config])
77
+ opts.delete(:cluster)
78
+ # Filter unrecognized fields just in case.
79
+ rem = opts.keys - members
80
+ opts.delete_if { |k| rem.include?(k) }
81
+ super(opts)
82
+ freeze
83
+ end
84
+ end
85
+
86
+ # ConsumerConfig is the consumer configuration.
87
+ #
88
+ # @!attribute durable_name
89
+ # @return [String]
90
+ # @!attribute deliver_policy
91
+ # @return [String]
92
+ # @!attribute ack_policy
93
+ # @return [String]
94
+ # @!attribute ack_wait
95
+ # @return [Integer]
96
+ # @!attribute max_deliver
97
+ # @return [Integer]
98
+ # @!attribute replay_policy
99
+ # @return [String]
100
+ # @!attribute max_waiting
101
+ # @return [Integer]
102
+ # @!attribute max_ack_pending
103
+ # @return [Integer]
104
+ 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={})
124
+ # Filter unrecognized fields just in case.
125
+ rem = opts.keys - members
126
+ opts.delete_if { |k| rem.include?(k) }
127
+ super(opts)
128
+ end
129
+ end
130
+
131
+ # StreamConfig represents the configuration of a stream from JetStream.
132
+ #
133
+ # @!attribute type
134
+ # @return [String]
135
+ # @!attribute config
136
+ # @return [Hash]
137
+ # @!attribute created
138
+ # @return [String]
139
+ # @!attribute state
140
+ # @return [StreamState]
141
+ # @!attribute did_create
142
+ # @return [Boolean]
143
+ # @!attribute name
144
+ # @return [String]
145
+ # @!attribute subjects
146
+ # @return [Array]
147
+ # @!attribute retention
148
+ # @return [String]
149
+ # @!attribute max_consumers
150
+ # @return [Integer]
151
+ # @!attribute max_msgs
152
+ # @return [Integer]
153
+ # @!attribute max_bytes
154
+ # @return [Integer]
155
+ # @!attribute max_age
156
+ # @return [Integer]
157
+ # @!attribute max_msgs_per_subject
158
+ # @return [Integer]
159
+ # @!attribute max_msg_size
160
+ # @return [Integer]
161
+ # @!attribute discard
162
+ # @return [String]
163
+ # @!attribute storage
164
+ # @return [String]
165
+ # @!attribute num_replicas
166
+ # @return [Integer]
167
+ # @!attribute duplicate_window
168
+ # @return [Integer]
169
+ StreamConfig = Struct.new(
170
+ :name,
171
+ :description,
172
+ :subjects,
173
+ :retention,
174
+ :max_consumers,
175
+ :max_msgs,
176
+ :max_bytes,
177
+ :discard,
178
+ :max_age,
179
+ :max_msgs_per_subject,
180
+ :max_msg_size,
181
+ :storage,
182
+ :num_replicas,
183
+ :no_ack,
184
+ :duplicate_window,
185
+ :placement,
186
+ :mirror,
187
+ :sources,
188
+ :sealed,
189
+ :deny_delete,
190
+ :deny_purge,
191
+ :allow_rollup_hdrs,
192
+ :republish,
193
+ :allow_direct,
194
+ :mirror_direct,
195
+ keyword_init: true) do
196
+ def initialize(opts={})
197
+ # Filter unrecognized fields just in case.
198
+ rem = opts.keys - members
199
+ opts.delete_if { |k| rem.include?(k) }
200
+ super(opts)
201
+ end
202
+ end
203
+
204
+ # StreamInfo is the info about a stream from JetStream.
205
+ #
206
+ # @!attribute type
207
+ # @return [String]
208
+ # @!attribute config
209
+ # @return [Hash]
210
+ # @!attribute created
211
+ # @return [String]
212
+ # @!attribute state
213
+ # @return [Hash]
214
+ # @!attribute domain
215
+ # @return [String]
216
+ StreamInfo = Struct.new(:type, :config, :created, :state, :domain,
217
+ keyword_init: true) do
218
+ def initialize(opts={})
219
+ opts[:config] = StreamConfig.new(opts[:config])
220
+ opts[:state] = StreamState.new(opts[:state])
221
+ opts[:created] = ::Time.parse(opts[:created])
222
+
223
+ # Filter fields and freeze.
224
+ rem = opts.keys - members
225
+ opts.delete_if { |k| rem.include?(k) }
226
+ super(opts)
227
+ freeze
228
+ end
229
+ end
230
+
231
+ # StreamState is the state of a stream.
232
+ #
233
+ # @!attribute messages
234
+ # @return [Integer]
235
+ # @!attribute bytes
236
+ # @return [Integer]
237
+ # @!attribute first_seq
238
+ # @return [Integer]
239
+ # @!attribute last_seq
240
+ # @return [Integer]
241
+ # @!attribute consumer_count
242
+ # @return [Integer]
243
+ 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={})
247
+ rem = opts.keys - members
248
+ opts.delete_if { |k| rem.include?(k) }
249
+ super(opts)
250
+ end
251
+ end
252
+
253
+ # StreamCreateResponse is the response from the JetStream $JS.API.STREAM.CREATE API.
254
+ #
255
+ # @!attribute type
256
+ # @return [String]
257
+ # @!attribute config
258
+ # @return [StreamConfig]
259
+ # @!attribute created
260
+ # @return [String]
261
+ # @!attribute state
262
+ # @return [StreamState]
263
+ # @!attribute did_create
264
+ # @return [Boolean]
265
+ StreamCreateResponse = Struct.new(:type, :config, :created, :state, :did_create,
266
+ keyword_init: true) do
267
+ def initialize(opts={})
268
+ rem = opts.keys - members
269
+ opts.delete_if { |k| rem.include?(k) }
270
+ opts[:config] = StreamConfig.new(opts[:config])
271
+ opts[:state] = StreamState.new(opts[:state])
272
+ super(opts)
273
+ freeze
274
+ end
275
+ end
276
+
277
+ RawStreamMsg = Struct.new(:subject, :seq, :data, :headers, keyword_init: true) do
278
+ def initialize(opts)
279
+ opts[:data] = Base64.decode64(opts[:data]) if opts[:data]
280
+ if opts[:hdrs]
281
+ header = Base64.decode64(opts[:hdrs])
282
+ hdr = {}
283
+ lines = header.lines
284
+ lines.slice(1, header.size).each do |line|
285
+ line.rstrip!
286
+ next if line.empty?
287
+ key, value = line.strip.split(/\s*:\s*/, 2)
288
+ hdr[key] = value
289
+ end
290
+ opts[:headers] = hdr
291
+ end
292
+
293
+ # Filter out members not present.
294
+ rem = opts.keys - members
295
+ opts.delete_if { |k| rem.include?(k) }
296
+ super(opts)
297
+ end
298
+
299
+ def sequence
300
+ self.seq
301
+ end
302
+ end
303
+ end
304
+ end
305
+ end
@@ -0,0 +1,104 @@
1
+ # Copyright 2021 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ module NATS
16
+ class JetStream
17
+ # Error is any error that may arise when interacting with JetStream.
18
+ class Error < NATS::IO::Error
19
+
20
+ # When there is a NATS::IO::NoResponders error after making a publish request.
21
+ class NoStreamResponse < Error; end
22
+
23
+ # When an invalid durable or consumer name was attempted to be used.
24
+ class InvalidDurableName < Error; end
25
+
26
+ # When an ack not longer valid.
27
+ class InvalidJSAck < Error; end
28
+
29
+ # When an ack has already been acked.
30
+ class MsgAlreadyAckd < Error; end
31
+
32
+ # When the delivered message does not behave as a message delivered by JetStream,
33
+ # for example when the ack reply has unrecognizable fields.
34
+ class NotJSMessage < Error; end
35
+
36
+ # When the stream name is invalid.
37
+ class InvalidStreamName < Error; end
38
+
39
+ # When the consumer name is invalid.
40
+ class InvalidConsumerName < Error; end
41
+
42
+ # When the server responds with an error from the JetStream API.
43
+ class APIError < Error
44
+ attr_reader :code, :err_code, :description, :stream, :seq
45
+
46
+ def initialize(params={})
47
+ @code = params[:code]
48
+ @err_code = params[:err_code]
49
+ @description = params[:description]
50
+ @stream = params[:stream]
51
+ @seq = params[:seq]
52
+ end
53
+
54
+ def to_s
55
+ "#{@description} (status_code=#{@code}, err_code=#{@err_code})"
56
+ end
57
+ end
58
+
59
+ # When JetStream is not currently available, this could be due to JetStream
60
+ # not being enabled or temporarily unavailable due to a leader election when
61
+ # running in cluster mode.
62
+ # This condition is represented with a message that has 503 status code header.
63
+ class ServiceUnavailable < APIError
64
+ def initialize(params={})
65
+ super(params)
66
+ @code ||= 503
67
+ end
68
+ end
69
+
70
+ # When there is a hard failure in the JetStream.
71
+ # This condition is represented with a message that has 500 status code header.
72
+ class ServerError < APIError
73
+ def initialize(params={})
74
+ super(params)
75
+ @code ||= 500
76
+ end
77
+ end
78
+
79
+ # When a JetStream object was not found.
80
+ # This condition is represented with a message that has 404 status code header.
81
+ class NotFound < APIError
82
+ def initialize(params={})
83
+ super(params)
84
+ @code ||= 404
85
+ end
86
+ end
87
+
88
+ # When the stream is not found.
89
+ class StreamNotFound < NotFound; end
90
+
91
+ # When the consumer or durable is not found by name.
92
+ class ConsumerNotFound < NotFound; end
93
+
94
+ # When the JetStream client makes an invalid request.
95
+ # This condition is represented with a message that has 400 status code header.
96
+ class BadRequest < APIError
97
+ def initialize(params={})
98
+ super(params)
99
+ @code ||= 400
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright 2021 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ module NATS
16
+ class JetStream
17
+ module JS
18
+ module Config
19
+ # AckPolicy
20
+ AckExplicit = ("explicit".freeze)
21
+ AckAll = ("all".freeze)
22
+ AckNone = ("none".freeze)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright 2021 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ module NATS
16
+ class JetStream
17
+ module JS
18
+ 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)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ # Copyright 2021 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ module NATS
16
+ class JetStream
17
+ module JS
18
+ module Status
19
+ CtrlMsg = ("100".freeze)
20
+ NoMsgs = ("404".freeze)
21
+ NotFound = ("404".freeze)
22
+ RequestTimeout = ("408".freeze)
23
+ ServiceUnavailable = ("503".freeze)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright 2021 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ module NATS
16
+ class JetStream
17
+ module JS
18
+ class Sub
19
+ attr_reader :js, :stream, :consumer, :nms
20
+
21
+ def initialize(opts={})
22
+ @js = opts[:js]
23
+ @stream = opts[:stream]
24
+ @consumer = opts[:consumer]
25
+ @nms = opts[:nms]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,93 @@
1
+ # Copyright 2021 The NATS Authors
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ require_relative 'js/config'
16
+ require_relative 'js/header'
17
+ require_relative 'js/status'
18
+ require_relative 'js/sub'
19
+
20
+ module NATS
21
+ class JetStream
22
+ # Misc internal functions to support JS API.
23
+ # @private
24
+ module JS
25
+ DefaultAPIPrefix = ("$JS.API".freeze)
26
+
27
+ class << self
28
+ def next_req_to_json(next_req)
29
+ req = {}
30
+ req[:batch] = next_req[:batch]
31
+ req[:expires] = next_req[:expires].to_i if next_req[:expires]
32
+ req[:no_wait] = next_req[:no_wait] if next_req[:no_wait]
33
+ req.to_json
34
+ end
35
+
36
+ def is_status_msg(msg)
37
+ return (!msg.nil? and (!msg.header.nil? and msg.header[Header::Status]))
38
+ end
39
+
40
+ # check_503_error raises exception when a NATS::Msg has a 503 status header.
41
+ # @param msg [NATS::Msg] The message with status headers.
42
+ # @raise [NATS::JetStream::Error::ServiceUnavailable]
43
+ def check_503_error(msg)
44
+ return if msg.nil? or msg.header.nil?
45
+ if msg.header[Header::Status] == Status::ServiceUnavailable
46
+ raise ::NATS::JetStream::Error::ServiceUnavailable
47
+ end
48
+ end
49
+
50
+ # from_msg takes a plain NATS::Msg and checks its headers to confirm
51
+ # if it was an error:
52
+ #
53
+ # msg.header={"Status"=>"503"})
54
+ # msg.header={"Status"=>"408", "Description"=>"Request Timeout"})
55
+ #
56
+ # @param msg [NATS::Msg] The message with status headers.
57
+ # @return [NATS::JetStream::API::Error]
58
+ def from_msg(msg)
59
+ check_503_error(msg)
60
+ code = msg.header[JS::Header::Status]
61
+ desc = msg.header[JS::Header::Desc]
62
+ return ::NATS::JetStream::API::Error.new({code: code, description: desc})
63
+ end
64
+
65
+ # from_error takes an API response that errored and maps the error
66
+ # into a JetStream error type based on the status and error code.
67
+ def from_error(err)
68
+ return unless err
69
+ case err[:code]
70
+ when 503
71
+ ::NATS::JetStream::Error::ServiceUnavailable.new(err)
72
+ when 500
73
+ ::NATS::JetStream::Error::ServerError.new(err)
74
+ when 404
75
+ case err[:err_code]
76
+ when 10059
77
+ ::NATS::JetStream::Error::StreamNotFound.new(err)
78
+ when 10014
79
+ ::NATS::JetStream::Error::ConsumerNotFound.new(err)
80
+ else
81
+ ::NATS::JetStream::Error::NotFound.new(err)
82
+ end
83
+ when 400
84
+ ::NATS::JetStream::Error::BadRequest.new(err)
85
+ else
86
+ ::NATS::JetStream::API::Error.new(err)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ private_constant :JS
92
+ end
93
+ end