nats-pure 2.5.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.
@@ -41,6 +41,27 @@ module NATS
41
41
  end
42
42
  end
43
43
 
44
+ # PriorityGroupState is the state of a priority group of a consumer
45
+ # (requires nats-server v2.11.0).
46
+ #
47
+ # @!attribute group
48
+ # @return [String] Name of the group.
49
+ # @!attribute pinned_client_id
50
+ # @return [String, nil] With the pinned_client priority policy, the
51
+ # pin id of the subscription that the group is pinned to.
52
+ # @!attribute pinned_ts
53
+ # @return [Time, nil] When the group was pinned.
54
+ PriorityGroupState = Struct.new(:group, :pinned_client_id, :pinned_ts,
55
+ keyword_init: true) do
56
+ def initialize(opts = {})
57
+ opts[:pinned_ts] = JS.parse_time(opts[:pinned_ts])
58
+ rem = opts.keys - members
59
+ opts.delete_if { |k| rem.include?(k) }
60
+ super
61
+ freeze
62
+ end
63
+ end
64
+
44
65
  # ConsumerInfo is the current status of a JetStream consumer.
45
66
  #
46
67
  # @!attribute stream_name
@@ -64,21 +85,43 @@ module NATS
64
85
  # @!attribute num_pending
65
86
  # @return [Integer]
66
87
  # @!attribute cluster
67
- # @return [Hash]
88
+ # The cluster of a clustered consumer, such as its leader, its
89
+ # replicas and, as leader_since, when the leader was elected
90
+ # (requires nats-server v2.12.0); nil on a standalone server. The
91
+ # values are the server's: leader_since is a String, and the
92
+ # active of the replicas is in nanoseconds.
93
+ # @return [Hash, nil]
94
+ # @!attribute ts
95
+ # When the server reported this info (requires nats-server v2.10.0).
96
+ # @return [Time]
97
+ # @!attribute paused
98
+ # True while the consumer is paused (requires nats-server v2.11.0).
99
+ # @return [Boolean, nil]
100
+ # @!attribute pause_remaining
101
+ # Seconds until a paused consumer resumes, rounded down, so 0 in its
102
+ # last second (requires nats-server v2.11.0).
103
+ # @return [Integer, nil]
104
+ # @!attribute priority_groups
105
+ # State of the consumer's priority groups (requires nats-server v2.11.0).
106
+ # @return [Array<PriorityGroupState>, nil]
68
107
  ConsumerInfo = Struct.new(:type, :stream_name, :name, :created,
69
108
  :config, :delivered, :ack_floor,
70
109
  :num_ack_pending, :num_redelivered, :num_waiting,
71
- :num_pending, :cluster, :push_bound,
110
+ :num_pending, :cluster, :push_bound, :ts,
111
+ :paused, :pause_remaining, :priority_groups,
72
112
  keyword_init: true) do
73
113
  def initialize(opts = {})
74
114
  opts[:created] = Time.parse(opts[:created])
115
+ opts[:ts] = Time.parse(opts[:ts]) if opts[:ts]
116
+ opts[:pause_remaining] = opts[:pause_remaining] / ::NATS::NANOSECONDS if opts[:pause_remaining]
117
+ opts[:priority_groups] = opts[:priority_groups].map { |state| PriorityGroupState.new(state) } if opts[:priority_groups]
75
118
  opts[:ack_floor] = SequenceInfo.new(opts[:ack_floor])
76
119
  opts[:delivered] = SequenceInfo.new(opts[:delivered])
77
- opts[:config][:ack_wait] = opts[:config][:ack_wait] / ::NATS::NANOSECONDS
120
+ opts[:config][:ack_wait] = opts[:config][:ack_wait] / ::NATS::NANOSECONDS if opts[:config][:ack_wait]
78
121
  opts[:config][:inactive_threshold] = opts[:config][:inactive_threshold] / ::NATS::NANOSECONDS if opts[:config][:inactive_threshold]
79
122
  opts[:config][:idle_heartbeat] = opts[:config][:idle_heartbeat] / ::NATS::NANOSECONDS if opts[:config][:idle_heartbeat]
123
+ opts[:config][:priority_timeout] = opts[:config][:priority_timeout] / ::NATS::NANOSECONDS if opts[:config][:priority_timeout]
80
124
  opts[:config] = ConsumerConfig.new(opts[:config])
81
- opts.delete(:cluster)
82
125
  # Filter unrecognized fields just in case.
83
126
  rem = opts.keys - members
84
127
  opts.delete_if { |k| rem.include?(k) }
@@ -96,7 +139,8 @@ module NATS
96
139
  # @!attribute ack_policy
97
140
  # @return [String]
98
141
  # @!attribute ack_wait
99
- # @return [Integer]
142
+ # Seconds; nil when the server omits it, as for consumers that do not ack.
143
+ # @return [Integer, nil]
100
144
  # @!attribute max_deliver
101
145
  # @return [Integer]
102
146
  # @!attribute replay_policy
@@ -105,6 +149,27 @@ module NATS
105
149
  # @return [Integer]
106
150
  # @!attribute max_ack_pending
107
151
  # @return [Integer]
152
+ # @!attribute pause_until
153
+ # Time until which the consumer delivers no messages, as a Time or
154
+ # as an RFC 3339 String; a fetched config has a String. The server
155
+ # takes it only when it creates the consumer: updates keep the pause,
156
+ # which pause_consumer and resume_consumer change. Requires
157
+ # nats-server v2.11.0; older ones create the consumer unpaused.
158
+ # @return [Time, String, nil]
159
+ # @!attribute priority_policy
160
+ # How the consumer serves the pulls of its priority groups: "none",
161
+ # "overflow", "pinned_client", or "prioritized" (requires
162
+ # nats-server v2.11.0, and v2.12.0 for "prioritized").
163
+ # @return [String, nil]
164
+ # @!attribute priority_groups
165
+ # Names of the consumer's priority groups, one of which each pull
166
+ # has to name (requires nats-server v2.11.0).
167
+ # @return [Array<String>, nil]
168
+ # @!attribute priority_timeout
169
+ # With the pinned_client priority policy, seconds after which a
170
+ # pinned subscription that stops pulling is unpinned
171
+ # (requires nats-server v2.11.0).
172
+ # @return [Integer, nil]
108
173
  ConsumerConfig = Struct.new(:name, :durable_name, :description,
109
174
  :deliver_policy, :opt_start_seq, :opt_start_time,
110
175
  :ack_policy, :ack_wait, :max_deliver, :backoff,
@@ -124,6 +189,8 @@ module NATS
124
189
  :mem_storage,
125
190
  # NATS v2.10 features
126
191
  :metadata, :filter_subjects, :max_bytes,
192
+ # NATS v2.11 features
193
+ :pause_until, :priority_policy, :priority_groups, :priority_timeout,
127
194
  keyword_init: true) do
128
195
  def initialize(opts = {})
129
196
  # Filter unrecognized fields just in case.
@@ -133,8 +200,54 @@ module NATS
133
200
  end
134
201
  end
135
202
 
203
+ # ConsumerPauseResponse is the result of pausing or resuming a consumer
204
+ # (requires nats-server v2.11.0).
205
+ #
206
+ # @!attribute paused
207
+ # @return [Boolean] Whether the consumer is paused.
208
+ # @!attribute pause_until
209
+ # @return [Time, nil] When the consumer resumes; nil once resumed. A time
210
+ # in the past does not pause the consumer, and paused is then false.
211
+ # @!attribute pause_remaining
212
+ # @return [Integer, nil] Seconds until the consumer resumes, rounded down,
213
+ # so 0 in its last second; nil when it is not paused.
214
+ ConsumerPauseResponse = Struct.new(:paused, :pause_until, :pause_remaining,
215
+ keyword_init: true) do
216
+ def initialize(opts = {})
217
+ opts[:pause_until] = JS.parse_time(opts[:pause_until])
218
+ opts[:pause_remaining] = opts[:pause_remaining] / ::NATS::NANOSECONDS if opts[:pause_remaining]
219
+ rem = opts.keys - members
220
+ opts.delete_if { |k| rem.include?(k) }
221
+ super
222
+ freeze
223
+ end
224
+ end
225
+
226
+ # ConsumerResetResponse is the result of resetting a consumer
227
+ # (requires nats-server v2.14.0).
228
+ #
229
+ # @!attribute info
230
+ # @return [ConsumerInfo] The consumer after the reset.
231
+ # @!attribute reset_seq
232
+ # @return [Integer] Stream sequence the consumer delivers from. The next
233
+ # message it delivers can come later, as the first one from there that
234
+ # matches its filter.
235
+ ConsumerResetResponse = Struct.new(:info, :reset_seq,
236
+ keyword_init: true) do
237
+ def initialize(opts = {})
238
+ reset_seq = opts[:reset_seq]
239
+ super(info: ConsumerInfo.new(opts), reset_seq: reset_seq)
240
+ freeze
241
+ end
242
+ end
243
+
136
244
  # StreamConfig represents the configuration of a stream from JetStream.
137
245
  #
246
+ # Settings left nil are not sent, and neither are the settings of
247
+ # nats-server 2.11 to 2.14 left at their defaults, such as false.
248
+ # Servers since v2.12.0, and v2.11 ones in strict mode, refuse the
249
+ # settings that they do not know.
250
+ #
138
251
  # @!attribute type
139
252
  # @return [String]
140
253
  # @!attribute config
@@ -165,12 +278,75 @@ module NATS
165
278
  # @return [Integer]
166
279
  # @!attribute discard
167
280
  # @return [String]
281
+ # @!attribute discard_new_per_subject
282
+ # Whether a subject that holds max_msgs_per_subject messages refuses
283
+ # new ones, instead of discarding its oldest. Needs discard "new" and
284
+ # max_msgs_per_subject; the server reports false as nil.
285
+ # @return [Boolean, nil]
168
286
  # @!attribute storage
169
287
  # @return [String]
170
288
  # @!attribute num_replicas
171
289
  # @return [Integer]
172
290
  # @!attribute duplicate_window
291
+ # Nanoseconds within which the stream stores a message only once for
292
+ # each Header::MSG_ID. Unless set, it is 2 minutes, except that
293
+ # mirrors, and since nats-server v2.14.0 streams with sources, get
294
+ # none: the messages published to them are not deduplicated.
295
+ # @return [Integer]
296
+ # @!attribute compression
297
+ # Storage compression of a file based stream, "s2" or "none"
298
+ # (requires nats-server v2.10.0).
299
+ # @return [String]
300
+ # @!attribute first_seq
301
+ # The sequence of the first message stored in a new stream
302
+ # (requires nats-server v2.10.0).
173
303
  # @return [Integer]
304
+ # @!attribute subject_transform
305
+ # Transform applied to the subject of every message stored, as
306
+ # `{src:, dest:}` (requires nats-server v2.10.0).
307
+ # @return [Hash]
308
+ # @!attribute consumer_limits
309
+ # Defaults and upper limits for the stream's consumers, as
310
+ # `{inactive_threshold:, max_ack_pending:}`. Like the other durations
311
+ # of a stream, inactive_threshold is in nanoseconds
312
+ # (requires nats-server v2.10.0).
313
+ # @return [Hash]
314
+ # @!attribute allow_msg_ttl
315
+ # Whether messages can be published with a TTL of their own
316
+ # (requires nats-server v2.11.0). Once enabled, it cannot be
317
+ # disabled, and before v2.11.2 it cannot be enabled by an update.
318
+ # @return [Boolean]
319
+ # @!attribute subject_delete_marker_ttl
320
+ # Nanoseconds to keep the marker that the server leaves when the last
321
+ # message of a subject expires, at least a second (requires
322
+ # nats-server v2.11.0). Before v2.11.2 it needs allow_msg_ttl. From
323
+ # v2.11.2 on, setting it enables allow_msg_ttl and allow_rollup_hdrs,
324
+ # and allows purges, so an update cannot set it on a stream that
325
+ # denies them.
326
+ # @return [Integer]
327
+ # @!attribute allow_msg_counter
328
+ # Whether the stream holds counters, which cannot change later
329
+ # (requires nats-server v2.12.0).
330
+ # @return [Boolean]
331
+ # @!attribute allow_atomic
332
+ # Whether messages can be published in atomic batches
333
+ # (requires nats-server v2.12.0).
334
+ # @return [Boolean]
335
+ # @!attribute allow_msg_schedules
336
+ # Whether messages can schedule messages (requires nats-server
337
+ # v2.12.0). Once enabled, it cannot be disabled. Setting it enables
338
+ # allow_rollup_hdrs and allows purges, so an update cannot set it on
339
+ # a stream that denies them.
340
+ # @return [Boolean]
341
+ # @!attribute persist_mode
342
+ # "async" to acknowledge messages before they are flushed to disk,
343
+ # or "default"; the server reports the default as nil. It cannot
344
+ # change later (requires nats-server v2.12.0).
345
+ # @return [String, nil]
346
+ # @!attribute allow_batched
347
+ # Whether messages can be published in fast batches
348
+ # (requires nats-server v2.14.0).
349
+ # @return [Boolean]
174
350
  StreamConfig = Struct.new(
175
351
  :name,
176
352
  :description,
@@ -198,6 +374,18 @@ module NATS
198
374
  :allow_direct,
199
375
  :mirror_direct,
200
376
  :metadata,
377
+ :compression,
378
+ :first_seq,
379
+ :subject_transform,
380
+ :consumer_limits,
381
+ :allow_msg_ttl,
382
+ :subject_delete_marker_ttl,
383
+ :allow_msg_counter,
384
+ :allow_atomic,
385
+ :allow_msg_schedules,
386
+ :persist_mode,
387
+ :allow_batched,
388
+ :discard_new_per_subject,
201
389
  keyword_init: true
202
390
  ) do
203
391
  def initialize(opts = {})
@@ -220,12 +408,32 @@ module NATS
220
408
  # @return [Hash]
221
409
  # @!attribute domain
222
410
  # @return [String]
411
+ # @!attribute mirror
412
+ # State of the stream's mirror, such as its lag and subject
413
+ # transforms, as a Hash.
414
+ # @return [Hash]
415
+ # @!attribute sources
416
+ # State of each of the stream's sources, such as its lag and subject
417
+ # transforms, as Hashes.
418
+ # @return [Array<Hash>]
419
+ # @!attribute cluster
420
+ # The cluster of the stream, such as its leader, its replicas and,
421
+ # as leader_since, when the leader was elected (requires nats-server
422
+ # v2.12.0). A standalone server reports only itself, as the leader.
423
+ # The values are the server's: leader_since is a String, and the
424
+ # active of the replicas is in nanoseconds.
425
+ # @return [Hash]
426
+ # @!attribute ts
427
+ # When the server reported this info (requires nats-server v2.10.0).
428
+ # @return [Time]
223
429
  StreamInfo = Struct.new(:type, :config, :created, :state, :domain,
430
+ :mirror, :sources, :cluster, :ts,
224
431
  keyword_init: true) do
225
432
  def initialize(opts = {})
226
433
  opts[:config] = StreamConfig.new(opts[:config])
227
434
  opts[:state] = StreamState.new(opts[:state])
228
435
  opts[:created] = ::Time.parse(opts[:created])
436
+ opts[:ts] = ::Time.parse(opts[:ts]) if opts[:ts]
229
437
 
230
438
  # Filter fields and freeze.
231
439
  rem = opts.keys - members
@@ -115,6 +115,31 @@ module NATS
115
115
  @code ||= 400
116
116
  end
117
117
  end
118
+
119
+ # When create_consumer finds the consumer already exists with a
120
+ # different configuration.
121
+ class ConsumerAlreadyExists < BadRequest; end
122
+
123
+ # When update_consumer finds no consumer to update. The server reports
124
+ # it as a bad request, so unlike ConsumerNotFound it is not NotFound.
125
+ class ConsumerDoesNotExist < BadRequest; end
126
+
127
+ # When reset_consumer is given a sequence that the consumer cannot be
128
+ # reset to: one before its start, or any for a consumer that does
129
+ # not deliver all messages or from a start sequence or time.
130
+ class ConsumerInvalidReset < BadRequest; end
131
+
132
+ # When a fetch from a consumer with the pinned_client priority policy
133
+ # finds the subscription no longer pinned, as its pin expired or it
134
+ # was unpinned. The subscription forgets its pin, so that its next
135
+ # fetch can be pinned again.
136
+ # This condition is represented with a message that has 423 status code header.
137
+ class PinIdMismatch < APIError
138
+ def initialize(params = {})
139
+ super
140
+ @code ||= 423
141
+ end
142
+ end
118
143
  end
119
144
  end
120
145
  end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2026 The NATS Authors
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module NATS
18
+ class JetStream
19
+ # Header names headers that publishers set for JetStream, and that
20
+ # JetStream sets on the messages that it stores, republishes or returns
21
+ # from direct gets.
22
+ #
23
+ # @example Publish unless the subject got another message since sequence 10
24
+ # js.publish("orders.1", data, header: {
25
+ # NATS::JetStream::Header::EXPECTED_LAST_SUBJECT_SEQUENCE => "10"
26
+ # })
27
+ module Header
28
+ # Id of the message; the stream stores a message only once for each
29
+ # id within its duplicate_window.
30
+ MSG_ID = "Nats-Msg-Id"
31
+ # Name of the stream that has to store the message.
32
+ EXPECTED_STREAM = "Nats-Expected-Stream"
33
+ # Sequence of the last message that the stream has to have.
34
+ EXPECTED_LAST_SEQUENCE = "Nats-Expected-Last-Sequence"
35
+ # Sequence of the last message that the subject has to have.
36
+ EXPECTED_LAST_SUBJECT_SEQUENCE = "Nats-Expected-Last-Subject-Sequence"
37
+ # Subject for EXPECTED_LAST_SUBJECT_SEQUENCE to check instead of the
38
+ # subject of the message (requires nats-server v2.11.0).
39
+ EXPECTED_LAST_SUBJECT_SEQUENCE_SUBJECT = "Nats-Expected-Last-Subject-Sequence-Subject"
40
+ # Id of the last message that the stream has to have.
41
+ EXPECTED_LAST_MSG_ID = "Nats-Expected-Last-Msg-Id"
42
+ # "sub" to remove the earlier messages of the subject, or "all" those
43
+ # of the stream, as the message is stored.
44
+ ROLLUP = "Nats-Rollup"
45
+
46
+ # TTL of the message: seconds, a Go duration such as "1h", or "never"
47
+ # (requires nats-server v2.11.0).
48
+ MSG_TTL = "Nats-TTL"
49
+ # Set by the server on the marker it leaves when the last message of a
50
+ # subject expires, to "MaxAge" (requires nats-server v2.11.0).
51
+ MARKER_REASON = "Nats-Marker-Reason"
52
+
53
+ # Set by the server on the messages that it republishes or returns
54
+ # from direct gets, to the stream of the message.
55
+ STREAM = "Nats-Stream"
56
+ # Set with STREAM, to the subject of the message.
57
+ SUBJECT = "Nats-Subject"
58
+ # Set with STREAM, to the sequence of the message in the stream.
59
+ SEQUENCE = "Nats-Sequence"
60
+ # Set with STREAM, to when the stream stored the message.
61
+ TIME_STAMP = "Nats-Time-Stamp"
62
+ # Set by the server on the messages that it republishes, to the
63
+ # sequence of the message before on the same subject, or "0".
64
+ LAST_SEQUENCE = "Nats-Last-Sequence"
65
+ # Set by the server on the messages that a stream sources, starting
66
+ # with the name of the stream they come from and their sequence there.
67
+ STREAM_SOURCE = "Nats-Stream-Source"
68
+
69
+ # Id of an atomic batch, of up to 64 characters
70
+ # (requires nats-server v2.12.0).
71
+ BATCH_ID = "Nats-Batch-Id"
72
+ # Sequence of the message in its atomic batch, from 1.
73
+ BATCH_SEQUENCE = "Nats-Batch-Sequence"
74
+ # "1" to commit an atomic batch with the message, or, since nats-server
75
+ # v2.14.0, "eob" to commit it without storing the message.
76
+ BATCH_COMMIT = "Nats-Batch-Commit"
77
+
78
+ # Makes the message a schedule: "@at" and an RFC 3339 time (requires
79
+ # nats-server v2.12.0), or "@every" and a Go duration, a cron
80
+ # expression with seconds, or "@hourly", "@daily" (or "@midnight"),
81
+ # "@weekly", "@monthly" or "@yearly" (or "@annually")
82
+ # (requires nats-server v2.14.0).
83
+ SCHEDULE = "Nats-Schedule"
84
+ # Subject that the schedule publishes its messages to.
85
+ SCHEDULE_TARGET = "Nats-Schedule-Target"
86
+ # Subject whose last message the schedule publishes, instead of its
87
+ # own (requires nats-server v2.14.0).
88
+ SCHEDULE_SOURCE = "Nats-Schedule-Source"
89
+ # MSG_TTL of the messages that the schedule publishes.
90
+ SCHEDULE_TTL = "Nats-Schedule-TTL"
91
+ # Time zone of a cron schedule, such as "Europe/Warsaw"
92
+ # (requires nats-server v2.14.0).
93
+ SCHEDULE_TIME_ZONE = "Nats-Schedule-Time-Zone"
94
+ # "sub" to roll up the target with each message that the schedule
95
+ # publishes (requires nats-server v2.14.0).
96
+ SCHEDULE_ROLLUP = "Nats-Schedule-Rollup"
97
+ # Set by the server on the messages that a schedule publishes, to the
98
+ # subject of the schedule. With SCHEDULE_NEXT "purge", names the
99
+ # schedule to cancel.
100
+ SCHEDULER = "Nats-Scheduler"
101
+ # Set by the server on the messages that a schedule publishes, to when
102
+ # the schedule fires next, or to "purge" when it does not. Published
103
+ # as "purge", cancels the SCHEDULER schedule.
104
+ SCHEDULE_NEXT = "Nats-Schedule-Next"
105
+
106
+ # The API level that the server has to have for a JetStream API
107
+ # request, a pull, a direct get, or a message of an atomic batch
108
+ # (since nats-server v2.12.1) or a fast batch, which it otherwise
109
+ # refuses with status 412, and err_code 10185 for API requests and
110
+ # batches (requires nats-server v2.12.0). The server stores batch
111
+ # messages without it, and plain publishes with it, as sent.
112
+ REQUIRED_API_LEVEL = "Nats-Required-Api-Level"
113
+ end
114
+ end
115
+ end
@@ -29,6 +29,7 @@ module NATS
29
29
  ExpectedLastMsgID = "Nats-Expected-Last-Msg-Id"
30
30
  LastConsumerSeq = "Nats-Last-Consumer"
31
31
  LastStreamSeq = "Nats-Last-Stream"
32
+ PinId = "Nats-Pin-Id"
32
33
 
33
34
  # rubocop:enable Naming/ConstantName
34
35
  end
@@ -24,6 +24,7 @@ module NATS
24
24
  NoMsgs = "404"
25
25
  NotFound = "404"
26
26
  RequestTimeout = "408"
27
+ PinIdMismatch = "423"
27
28
  ServiceUnavailable = "503"
28
29
 
29
30
  # rubocop:enable Naming/ConstantName
@@ -32,11 +32,28 @@ module NATS
32
32
  req[:batch] = next_req[:batch]
33
33
  req[:expires] = next_req[:expires].to_i if next_req[:expires]
34
34
  req[:no_wait] = next_req[:no_wait] if next_req[:no_wait]
35
+ # Priority groups (requires nats-server v2.11.0).
36
+ req.merge!(next_req.slice(:group, :min_pending, :min_ack_pending, :priority, :id).compact)
35
37
  req.to_json
36
38
  end
37
39
 
40
+ # parse_time parses a time from the server, which sends Go's zero
41
+ # time for a time that is not set.
42
+ def parse_time(time)
43
+ return if time.nil?
44
+
45
+ time = ::Time.parse(time)
46
+ time unless time.year == 1
47
+ end
48
+
49
+ # is_status_msg tells whether the server sent a message as a status:
50
+ # one with a Status header and no reply. A message of a stream can
51
+ # have a Status header too, but a consumer delivers it with a reply
52
+ # to ack it.
38
53
  def is_status_msg(msg)
39
- (!msg.nil? and (!msg.header.nil? and msg.header[Header::Status]))
54
+ return false if msg.nil? || msg.header.nil?
55
+
56
+ !msg.header[Header::Status].nil? && msg.reply.to_s.empty?
40
57
  end
41
58
 
42
59
  # check_503_error raises exception when a NATS::Msg has a 503 status header.
@@ -61,6 +78,8 @@ module NATS
61
78
  check_503_error(msg)
62
79
  code = msg.header[JS::Header::Status]
63
80
  desc = msg.header[JS::Header::Desc]
81
+ return ::NATS::JetStream::Error::PinIdMismatch.new({description: desc}) if code == Status::PinIdMismatch
82
+
64
83
  ::NATS::JetStream::API::Error.new({code: code, description: desc})
65
84
  end
66
85
 
@@ -83,7 +102,16 @@ module NATS
83
102
  ::NATS::JetStream::Error::NotFound.new(err)
84
103
  end
85
104
  when 400
86
- ::NATS::JetStream::Error::BadRequest.new(err)
105
+ case err[:err_code]
106
+ when 10148
107
+ ::NATS::JetStream::Error::ConsumerAlreadyExists.new(err)
108
+ when 10149
109
+ ::NATS::JetStream::Error::ConsumerDoesNotExist.new(err)
110
+ when 10204
111
+ ::NATS::JetStream::Error::ConsumerInvalidReset.new(err)
112
+ else
113
+ ::NATS::JetStream::Error::BadRequest.new(err)
114
+ end
87
115
  else
88
116
  ::NATS::JetStream::API::Error.new(err)
89
117
  end