nats-pure 2.2.0 → 2.2.1

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 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