nats-pure 0.7.2 → 2.4.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -0
  3. data/README.md +251 -0
  4. data/lib/nats/client.rb +16 -0
  5. data/lib/nats/io/client.rb +1559 -1277
  6. data/lib/nats/io/errors.rb +74 -0
  7. data/lib/nats/io/jetstream/api.rb +309 -0
  8. data/lib/nats/io/jetstream/errors.rb +104 -0
  9. data/lib/nats/io/jetstream/js/config.rb +26 -0
  10. data/lib/nats/io/jetstream/js/header.rb +31 -0
  11. data/lib/nats/io/jetstream/js/status.rb +27 -0
  12. data/lib/nats/io/jetstream/js/sub.rb +30 -0
  13. data/lib/nats/io/jetstream/js.rb +93 -0
  14. data/lib/nats/io/jetstream/manager.rb +303 -0
  15. data/lib/nats/io/jetstream/msg/ack.rb +57 -0
  16. data/lib/nats/io/jetstream/msg/ack_methods.rb +111 -0
  17. data/lib/nats/io/jetstream/msg/metadata.rb +37 -0
  18. data/lib/nats/io/jetstream/msg.rb +26 -0
  19. data/lib/nats/io/jetstream/pull_subscription.rb +260 -0
  20. data/lib/nats/io/jetstream/push_subscription.rb +42 -0
  21. data/lib/nats/io/jetstream.rb +344 -0
  22. data/lib/nats/io/kv/api.rb +39 -0
  23. data/lib/nats/io/kv/bucket_status.rb +38 -0
  24. data/lib/nats/io/kv/errors.rb +60 -0
  25. data/lib/nats/io/kv/manager.rb +89 -0
  26. data/lib/nats/io/kv.rb +178 -0
  27. data/lib/nats/io/msg.rb +58 -0
  28. data/lib/nats/io/parser.rb +7 -7
  29. data/lib/nats/io/rails.rb +29 -0
  30. data/lib/nats/io/subscription.rb +157 -0
  31. data/lib/nats/io/version.rb +8 -4
  32. data/lib/nats/io/websocket.rb +75 -0
  33. data/lib/nats/nuid.rb +3 -1
  34. data/lib/nats.rb +39 -0
  35. data/sig/nats/io/client.rbs +304 -0
  36. data/sig/nats/io/errors.rbs +54 -0
  37. data/sig/nats/io/jetstream/api.rbs +35 -0
  38. data/sig/nats/io/jetstream/errors.rbs +54 -0
  39. data/sig/nats/io/jetstream/js/config.rbs +11 -0
  40. data/sig/nats/io/jetstream/js/header.rbs +17 -0
  41. data/sig/nats/io/jetstream/js/status.rbs +13 -0
  42. data/sig/nats/io/jetstream/js/sub.rbs +14 -0
  43. data/sig/nats/io/jetstream/js.rbs +27 -0
  44. data/sig/nats/io/jetstream/manager.rbs +33 -0
  45. data/sig/nats/io/jetstream/msg/ack.rbs +35 -0
  46. data/sig/nats/io/jetstream/msg/ack_methods.rbs +25 -0
  47. data/sig/nats/io/jetstream/msg/metadata.rbs +15 -0
  48. data/sig/nats/io/jetstream/msg.rbs +6 -0
  49. data/sig/nats/io/jetstream/pull_subscription.rbs +14 -0
  50. data/sig/nats/io/jetstream/push_subscription.rbs +7 -0
  51. data/sig/nats/io/jetstream.rbs +15 -0
  52. data/sig/nats/io/kv/api.rbs +8 -0
  53. data/sig/nats/io/kv/bucket_status.rbs +17 -0
  54. data/sig/nats/io/kv/errors.rbs +30 -0
  55. data/sig/nats/io/kv/manager.rbs +11 -0
  56. data/sig/nats/io/kv.rbs +39 -0
  57. data/sig/nats/io/msg.rbs +14 -0
  58. data/sig/nats/io/parser.rbs +32 -0
  59. data/sig/nats/io/subscription.rbs +33 -0
  60. data/sig/nats/io/version.rbs +9 -0
  61. data/sig/nats/nuid.rbs +32 -0
  62. metadata +74 -4
@@ -0,0 +1,74 @@
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
+ module IO
17
+ class Error < StandardError; end
18
+
19
+ # When the NATS server sends us an 'ERR' message.
20
+ class ServerError < Error; end
21
+
22
+ # When we detect error on the client side.
23
+ class ClientError < Error; end
24
+
25
+ # When we cannot connect to the server (either initially or after a reconnect).
26
+ class ConnectError < Error; end
27
+
28
+ # When we cannot connect to the server because authorization failed.
29
+ class AuthError < ConnectError; end
30
+
31
+ # When we cannot connect serverince there are no servers available.
32
+ class NoServersError < ConnectError; end
33
+
34
+ # When there are no subscribers available to respond.
35
+ class NoRespondersError < ConnectError; end
36
+
37
+ # When the connection exhausts max number of pending pings replies.
38
+ class StaleConnectionError < Error; end
39
+
40
+ # When we do not get a result within a specified time.
41
+ class Timeout < Error; end
42
+
43
+ # When there is an i/o timeout with the socket.
44
+ class SocketTimeoutError < Timeout; end
45
+
46
+ # When we use an invalid subject.
47
+ class BadSubject < Error; end
48
+
49
+ # When an invalid subscription is used, like one already unsubscribed
50
+ # or when the NATS connection is already closed.
51
+ class BadSubscription < Error; end
52
+
53
+ # When a subscription hits the pending messages limit.
54
+ class SlowConsumer < Error; end
55
+
56
+ # When an action cannot be done because client is draining.
57
+ class ConnectionDrainingError < Error; end
58
+
59
+ # When drain takes too long to complete.
60
+ class DrainTimeoutError < Error; end
61
+
62
+ # When a fork is detected, but the client is not configured to re-connect automatically.
63
+ class ForkDetectedError < Error; end
64
+
65
+ # When tried to send command after connection has been closed.
66
+ class ConnectionClosedError < Error; end
67
+ end
68
+
69
+ # Timeout is raised when the client gives up waiting for a response from a service.
70
+ Timeout = ::NATS::IO::Timeout
71
+
72
+ # Error is any error thrown by the client library.
73
+ Error = ::NATS::IO::Error
74
+ end
@@ -0,0 +1,309 @@
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
+
123
+ # NATS v2.10 features
124
+ :metadata, :filter_subjects, :max_bytes,
125
+ keyword_init: true) do
126
+ def initialize(opts={})
127
+ # Filter unrecognized fields just in case.
128
+ rem = opts.keys - members
129
+ opts.delete_if { |k| rem.include?(k) }
130
+ super(opts)
131
+ end
132
+ end
133
+
134
+ # StreamConfig represents the configuration of a stream from JetStream.
135
+ #
136
+ # @!attribute type
137
+ # @return [String]
138
+ # @!attribute config
139
+ # @return [Hash]
140
+ # @!attribute created
141
+ # @return [String]
142
+ # @!attribute state
143
+ # @return [StreamState]
144
+ # @!attribute did_create
145
+ # @return [Boolean]
146
+ # @!attribute name
147
+ # @return [String]
148
+ # @!attribute subjects
149
+ # @return [Array]
150
+ # @!attribute retention
151
+ # @return [String]
152
+ # @!attribute max_consumers
153
+ # @return [Integer]
154
+ # @!attribute max_msgs
155
+ # @return [Integer]
156
+ # @!attribute max_bytes
157
+ # @return [Integer]
158
+ # @!attribute max_age
159
+ # @return [Integer]
160
+ # @!attribute max_msgs_per_subject
161
+ # @return [Integer]
162
+ # @!attribute max_msg_size
163
+ # @return [Integer]
164
+ # @!attribute discard
165
+ # @return [String]
166
+ # @!attribute storage
167
+ # @return [String]
168
+ # @!attribute num_replicas
169
+ # @return [Integer]
170
+ # @!attribute duplicate_window
171
+ # @return [Integer]
172
+ StreamConfig = Struct.new(
173
+ :name,
174
+ :description,
175
+ :subjects,
176
+ :retention,
177
+ :max_consumers,
178
+ :max_msgs,
179
+ :max_bytes,
180
+ :discard,
181
+ :max_age,
182
+ :max_msgs_per_subject,
183
+ :max_msg_size,
184
+ :storage,
185
+ :num_replicas,
186
+ :no_ack,
187
+ :duplicate_window,
188
+ :placement,
189
+ :mirror,
190
+ :sources,
191
+ :sealed,
192
+ :deny_delete,
193
+ :deny_purge,
194
+ :allow_rollup_hdrs,
195
+ :republish,
196
+ :allow_direct,
197
+ :mirror_direct,
198
+ :metadata,
199
+ keyword_init: true) do
200
+ def initialize(opts={})
201
+ # Filter unrecognized fields just in case.
202
+ rem = opts.keys - members
203
+ opts.delete_if { |k| rem.include?(k) }
204
+ super(opts)
205
+ end
206
+ end
207
+
208
+ # StreamInfo is the info about a stream from JetStream.
209
+ #
210
+ # @!attribute type
211
+ # @return [String]
212
+ # @!attribute config
213
+ # @return [Hash]
214
+ # @!attribute created
215
+ # @return [String]
216
+ # @!attribute state
217
+ # @return [Hash]
218
+ # @!attribute domain
219
+ # @return [String]
220
+ StreamInfo = Struct.new(:type, :config, :created, :state, :domain,
221
+ keyword_init: true) do
222
+ def initialize(opts={})
223
+ opts[:config] = StreamConfig.new(opts[:config])
224
+ opts[:state] = StreamState.new(opts[:state])
225
+ opts[:created] = ::Time.parse(opts[:created])
226
+
227
+ # Filter fields and freeze.
228
+ rem = opts.keys - members
229
+ opts.delete_if { |k| rem.include?(k) }
230
+ super(opts)
231
+ freeze
232
+ end
233
+ end
234
+
235
+ # StreamState is the state of a stream.
236
+ #
237
+ # @!attribute messages
238
+ # @return [Integer]
239
+ # @!attribute bytes
240
+ # @return [Integer]
241
+ # @!attribute first_seq
242
+ # @return [Integer]
243
+ # @!attribute last_seq
244
+ # @return [Integer]
245
+ # @!attribute consumer_count
246
+ # @return [Integer]
247
+ 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
+ rem = opts.keys - members
252
+ opts.delete_if { |k| rem.include?(k) }
253
+ super(opts)
254
+ end
255
+ end
256
+
257
+ # StreamCreateResponse is the response from the JetStream $JS.API.STREAM.CREATE API.
258
+ #
259
+ # @!attribute type
260
+ # @return [String]
261
+ # @!attribute config
262
+ # @return [StreamConfig]
263
+ # @!attribute created
264
+ # @return [String]
265
+ # @!attribute state
266
+ # @return [StreamState]
267
+ # @!attribute did_create
268
+ # @return [Boolean]
269
+ StreamCreateResponse = Struct.new(:type, :config, :created, :state, :did_create,
270
+ keyword_init: true) do
271
+ def initialize(opts={})
272
+ rem = opts.keys - members
273
+ opts.delete_if { |k| rem.include?(k) }
274
+ opts[:config] = StreamConfig.new(opts[:config])
275
+ opts[:state] = StreamState.new(opts[:state])
276
+ super(opts)
277
+ freeze
278
+ end
279
+ end
280
+
281
+ RawStreamMsg = Struct.new(:subject, :seq, :data, :headers, keyword_init: true) do
282
+ def initialize(opts)
283
+ opts[:data] = Base64.decode64(opts[:data]) if opts[:data]
284
+ if opts[:hdrs]
285
+ header = Base64.decode64(opts[:hdrs])
286
+ hdr = {}
287
+ lines = header.lines
288
+ lines.slice(1, header.size).each do |line|
289
+ line.rstrip!
290
+ next if line.empty?
291
+ key, value = line.strip.split(/\s*:\s*/, 2)
292
+ hdr[key] = value
293
+ end
294
+ opts[:headers] = hdr
295
+ end
296
+
297
+ # Filter out members not present.
298
+ rem = opts.keys - members
299
+ opts.delete_if { |k| rem.include?(k) }
300
+ super(opts)
301
+ end
302
+
303
+ def sequence
304
+ self.seq
305
+ end
306
+ end
307
+ end
308
+ end
309
+ 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