nats-pure 2.4.0 → 2.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +10 -3
- data/lib/nats/client.rb +7 -3
- data/lib/nats/io/client.rb +303 -280
- data/lib/nats/io/errors.rb +2 -0
- data/lib/nats/io/jetstream/api.rb +53 -50
- data/lib/nats/io/jetstream/errors.rb +30 -14
- data/lib/nats/io/jetstream/js/config.rb +9 -3
- data/lib/nats/io/jetstream/js/header.rb +15 -9
- data/lib/nats/io/jetstream/js/status.rb +11 -5
- data/lib/nats/io/jetstream/js/sub.rb +4 -2
- data/lib/nats/io/jetstream/js.rb +10 -8
- data/lib/nats/io/jetstream/manager.rb +103 -101
- data/lib/nats/io/jetstream/msg/ack.rb +15 -9
- data/lib/nats/io/jetstream/msg/ack_methods.rb +24 -22
- data/lib/nats/io/jetstream/msg/metadata.rb +9 -7
- data/lib/nats/io/jetstream/msg.rb +11 -4
- data/lib/nats/io/jetstream/pull_subscription.rb +21 -10
- data/lib/nats/io/jetstream/push_subscription.rb +3 -1
- data/lib/nats/io/jetstream.rb +102 -106
- data/lib/nats/io/kv/api.rb +7 -3
- data/lib/nats/io/kv/bucket_status.rb +7 -5
- data/lib/nats/io/kv/errors.rb +25 -2
- data/lib/nats/io/kv/manager.rb +19 -10
- data/lib/nats/io/kv.rb +359 -22
- data/lib/nats/io/msg.rb +19 -19
- data/lib/nats/io/parser.rb +23 -23
- data/lib/nats/io/rails.rb +2 -0
- data/lib/nats/io/subscription.rb +25 -22
- data/lib/nats/io/version.rb +4 -2
- data/lib/nats/io/websocket.rb +10 -8
- data/lib/nats/nuid.rb +33 -22
- data/lib/nats/service/callbacks.rb +22 -0
- data/lib/nats/service/endpoint.rb +155 -0
- data/lib/nats/service/errors.rb +44 -0
- data/lib/nats/service/group.rb +37 -0
- data/lib/nats/service/monitoring.rb +108 -0
- data/lib/nats/service/stats.rb +52 -0
- data/lib/nats/service/status.rb +66 -0
- data/lib/nats/service/validator.rb +31 -0
- data/lib/nats/service.rb +121 -0
- data/lib/nats/utils/list.rb +26 -0
- data/lib/nats-pure.rb +5 -0
- data/lib/nats.rb +10 -6
- metadata +176 -5
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -31,15 +33,15 @@ module NATS
|
|
31
33
|
# @param params [Hash] Options to customize API request.
|
32
34
|
# @option params [Float] :timeout Time to wait for response.
|
33
35
|
# @return [JetStream::API::StreamCreateResponse] The result of creating a Stream.
|
34
|
-
def add_stream(config, params={})
|
35
|
-
config = if
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
def add_stream(config, params = {})
|
37
|
+
config = if !config.is_a?(JetStream::API::StreamConfig)
|
38
|
+
JetStream::API::StreamConfig.new(config)
|
39
|
+
else
|
40
|
+
config
|
41
|
+
end
|
40
42
|
stream = config[:name]
|
41
43
|
raise ArgumentError.new(":name is required to create streams") unless stream
|
42
|
-
raise ArgumentError.new("Spaces, tabs, period (.), greater than (>) or asterisk (*) are prohibited in stream names") if stream =~ /(\s
|
44
|
+
raise ArgumentError.new("Spaces, tabs, period (.), greater than (>) or asterisk (*) are prohibited in stream names") if stream =~ /(\s|\.|>|\*)/
|
43
45
|
req_subject = "#{@prefix}.STREAM.CREATE.#{stream}"
|
44
46
|
|
45
47
|
cfg = config.to_h.compact
|
@@ -52,11 +54,11 @@ module NATS
|
|
52
54
|
# @param params [Hash] Options to customize API request.
|
53
55
|
# @option params [Float] :timeout Time to wait for response.
|
54
56
|
# @return [JetStream::API::StreamInfo] The latest StreamInfo of the stream.
|
55
|
-
def stream_info(stream, params={})
|
56
|
-
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil?
|
57
|
+
def stream_info(stream, params = {})
|
58
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? || stream.empty?
|
57
59
|
|
58
60
|
req_subject = "#{@prefix}.STREAM.INFO.#{stream}"
|
59
|
-
result = api_request(req_subject,
|
61
|
+
result = api_request(req_subject, "", params)
|
60
62
|
JetStream::API::StreamInfo.new(result)
|
61
63
|
end
|
62
64
|
|
@@ -65,15 +67,15 @@ module NATS
|
|
65
67
|
# @param params [Hash] Options to customize API request.
|
66
68
|
# @option params [Float] :timeout Time to wait for response.
|
67
69
|
# @return [JetStream::API::StreamCreateResponse] The result of creating a Stream.
|
68
|
-
def update_stream(config, params={})
|
69
|
-
config = if
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
def update_stream(config, params = {})
|
71
|
+
config = if !config.is_a?(JetStream::API::StreamConfig)
|
72
|
+
JetStream::API::StreamConfig.new(config)
|
73
|
+
else
|
74
|
+
config
|
75
|
+
end
|
74
76
|
stream = config[:name]
|
75
77
|
raise ArgumentError.new(":name is required to create streams") unless stream
|
76
|
-
raise ArgumentError.new("Spaces, tabs, period (.), greater than (>) or asterisk (*) are prohibited in stream names") if stream =~ /(\s
|
78
|
+
raise ArgumentError.new("Spaces, tabs, period (.), greater than (>) or asterisk (*) are prohibited in stream names") if stream =~ /(\s|\.|>|\*)/
|
77
79
|
req_subject = "#{@prefix}.STREAM.UPDATE.#{stream}"
|
78
80
|
cfg = config.to_h.compact
|
79
81
|
result = api_request(req_subject, cfg.to_json, params)
|
@@ -85,11 +87,11 @@ module NATS
|
|
85
87
|
# @param params [Hash] Options to customize API request.
|
86
88
|
# @option params [Float] :timeout Time to wait for response.
|
87
89
|
# @return [Boolean]
|
88
|
-
def delete_stream(stream, params={})
|
89
|
-
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil?
|
90
|
+
def delete_stream(stream, params = {})
|
91
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? || stream.empty?
|
90
92
|
|
91
93
|
req_subject = "#{@prefix}.STREAM.DELETE.#{stream}"
|
92
|
-
result = api_request(req_subject,
|
94
|
+
result = api_request(req_subject, "", params)
|
93
95
|
result[:success]
|
94
96
|
end
|
95
97
|
|
@@ -99,46 +101,45 @@ module NATS
|
|
99
101
|
# @param params [Hash] Options to customize API request.
|
100
102
|
# @option params [Float] :timeout Time to wait for response.
|
101
103
|
# @return [JetStream::API::ConsumerInfo] The result of creating a Consumer.
|
102
|
-
def add_consumer(stream, config, params={})
|
103
|
-
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil?
|
104
|
-
config = if
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
def add_consumer(stream, config, params = {})
|
105
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? || stream.empty?
|
106
|
+
config = if !config.is_a?(JetStream::API::ConsumerConfig)
|
107
|
+
JetStream::API::ConsumerConfig.new(config)
|
108
|
+
else
|
109
|
+
config
|
110
|
+
end
|
109
111
|
config[:name] ||= config[:durable_name]
|
110
|
-
req_subject =
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
112
|
+
req_subject = if config[:name]
|
113
|
+
###############################################################################
|
114
|
+
# #
|
115
|
+
# Using names is the supported way of creating consumers (NATS +v2.9.0. #
|
116
|
+
# #
|
117
|
+
###############################################################################
|
118
|
+
if config[:filter_subject] && config[:filter_subject] != ">"
|
119
|
+
"#{@prefix}.CONSUMER.CREATE.#{stream}.#{config[:name]}.#{config[:filter_subject]}"
|
120
|
+
else
|
121
|
+
##############################################################################
|
122
|
+
# #
|
123
|
+
# Endpoint to support creating ANY consumer with multi-filters (NATS +v2.10) #
|
124
|
+
# #
|
125
|
+
##############################################################################
|
126
|
+
"#{@prefix}.CONSUMER.CREATE.#{stream}.#{config[:name]}"
|
127
|
+
end
|
128
|
+
elsif config[:durable_name]
|
129
|
+
###############################################################################
|
130
|
+
# #
|
131
|
+
# Endpoint to support creating DURABLES before NATS v2.9.0. #
|
132
|
+
# #
|
133
|
+
###############################################################################
|
134
|
+
"#{@prefix}.CONSUMER.DURABLE.CREATE.#{stream}.#{config[:durable_name]}"
|
135
|
+
else
|
136
|
+
###############################################################################
|
137
|
+
# #
|
138
|
+
# Endpoint to support creating EPHEMERALS before NATS v2.9.0. #
|
139
|
+
# #
|
140
|
+
###############################################################################
|
141
|
+
"#{@prefix}.CONSUMER.CREATE.#{stream}"
|
142
|
+
end
|
142
143
|
|
143
144
|
config[:ack_policy] ||= JS::Config::AckExplicit
|
144
145
|
# Check if have to normalize ack wait so that it is in nanoseconds for Go compat.
|
@@ -150,6 +151,10 @@ module NATS
|
|
150
151
|
raise ArgumentError.new("nats: invalid inactive threshold") unless config[:inactive_threshold].is_a?(Integer)
|
151
152
|
config[:inactive_threshold] = config[:inactive_threshold] * ::NATS::NANOSECONDS
|
152
153
|
end
|
154
|
+
if config[:idle_heartbeat]
|
155
|
+
raise ArgumentError.new("nats: invalid idle heartbeat") unless config[:idle_heartbeat].is_a?(Integer)
|
156
|
+
config[:idle_heartbeat] = config[:idle_heartbeat] * ::NATS::NANOSECONDS
|
157
|
+
end
|
153
158
|
|
154
159
|
cfg = config.to_h.compact
|
155
160
|
req = {
|
@@ -167,12 +172,12 @@ module NATS
|
|
167
172
|
# @param params [Hash] Options to customize API request.
|
168
173
|
# @option params [Float] :timeout Time to wait for response.
|
169
174
|
# @return [JetStream::API::ConsumerInfo] The latest ConsumerInfo of the consumer.
|
170
|
-
def consumer_info(stream, consumer, params={})
|
171
|
-
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil?
|
172
|
-
raise JetStream::Error::InvalidConsumerName.new("nats: invalid consumer name") if consumer.nil?
|
175
|
+
def consumer_info(stream, consumer, params = {})
|
176
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? || stream.empty?
|
177
|
+
raise JetStream::Error::InvalidConsumerName.new("nats: invalid consumer name") if consumer.nil? || consumer.empty?
|
173
178
|
|
174
179
|
req_subject = "#{@prefix}.CONSUMER.INFO.#{stream}.#{consumer}"
|
175
|
-
result = api_request(req_subject,
|
180
|
+
result = api_request(req_subject, "", params)
|
176
181
|
JetStream::API::ConsumerInfo.new(result)
|
177
182
|
end
|
178
183
|
|
@@ -182,12 +187,12 @@ module NATS
|
|
182
187
|
# @param params [Hash] Options to customize API request.
|
183
188
|
# @option params [Float] :timeout Time to wait for response.
|
184
189
|
# @return [Boolean]
|
185
|
-
def delete_consumer(stream, consumer, params={})
|
186
|
-
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil?
|
187
|
-
raise JetStream::Error::InvalidConsumerName.new("nats: invalid consumer name") if consumer.nil?
|
190
|
+
def delete_consumer(stream, consumer, params = {})
|
191
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? || stream.empty?
|
192
|
+
raise JetStream::Error::InvalidConsumerName.new("nats: invalid consumer name") if consumer.nil? || consumer.empty?
|
188
193
|
|
189
194
|
req_subject = "#{@prefix}.CONSUMER.DELETE.#{stream}.#{consumer}"
|
190
|
-
result = api_request(req_subject,
|
195
|
+
result = api_request(req_subject, "", params)
|
191
196
|
result[:success]
|
192
197
|
end
|
193
198
|
|
@@ -197,9 +202,9 @@ module NATS
|
|
197
202
|
# @param params [Hash] Options to customize API request.
|
198
203
|
# @option params [Float] :timeout Time to wait for response.
|
199
204
|
# @return [String] The name of the JetStream stream for the subject.
|
200
|
-
def find_stream_name_by_subject(subject, params={})
|
205
|
+
def find_stream_name_by_subject(subject, params = {})
|
201
206
|
req_subject = "#{@prefix}.STREAM.NAMES"
|
202
|
-
req = {
|
207
|
+
req = {subject: subject}
|
203
208
|
result = api_request(req_subject, req.to_json, params)
|
204
209
|
raise JetStream::Error::NotFound unless result[:streams]
|
205
210
|
|
@@ -213,23 +218,22 @@ module NATS
|
|
213
218
|
# @option seq [Integer] Sequence number of a message.
|
214
219
|
# @option subject [String] Subject of the message.
|
215
220
|
# @option direct [Boolean] Use direct mode to for faster access (requires NATS v2.9.0)
|
216
|
-
def get_msg(stream_name, params={})
|
221
|
+
def get_msg(stream_name, params = {})
|
217
222
|
req = {}
|
218
|
-
|
219
|
-
when params[:next]
|
223
|
+
if params[:next]
|
220
224
|
req[:seq] = params[:seq]
|
221
225
|
req[:next_by_subj] = params[:subject]
|
222
|
-
|
226
|
+
elsif params[:seq]
|
223
227
|
req[:seq] = params[:seq]
|
224
|
-
|
228
|
+
elsif params[:subject]
|
225
229
|
req[:last_by_subj] = params[:subject]
|
226
230
|
end
|
227
231
|
|
228
232
|
data = req.to_json
|
229
233
|
if params[:direct]
|
230
|
-
if params[:subject]
|
234
|
+
if params[:subject] && !(params[:seq])
|
231
235
|
# last_by_subject type request requires no payload.
|
232
|
-
data =
|
236
|
+
data = ""
|
233
237
|
req_subject = "#{@prefix}.DIRECT.GET.#{stream_name}.#{params[:subject]}"
|
234
238
|
else
|
235
239
|
req_subject = "#{@prefix}.DIRECT.GET.#{stream_name}"
|
@@ -238,16 +242,14 @@ module NATS
|
|
238
242
|
req_subject = "#{@prefix}.STREAM.MSG.GET.#{stream_name}"
|
239
243
|
end
|
240
244
|
resp = api_request(req_subject, data, direct: params[:direct])
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
msg
|
245
|
+
if params[:direct]
|
246
|
+
_lift_msg_to_raw_msg(resp)
|
247
|
+
else
|
248
|
+
JetStream::API::RawStreamMsg.new(resp[:message])
|
249
|
+
end
|
248
250
|
end
|
249
251
|
|
250
|
-
def get_last_msg(stream_name, subject, params={})
|
252
|
+
def get_last_msg(stream_name, subject, params = {})
|
251
253
|
params[:subject] = subject
|
252
254
|
get_msg(stream_name, params)
|
253
255
|
end
|
@@ -258,20 +260,20 @@ module NATS
|
|
258
260
|
|
259
261
|
private
|
260
262
|
|
261
|
-
def api_request(req_subject, req="", params={})
|
263
|
+
def api_request(req_subject, req = "", params = {})
|
262
264
|
params[:timeout] ||= @opts[:timeout]
|
263
265
|
msg = begin
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
266
|
+
@nc.request(req_subject, req, **params)
|
267
|
+
rescue NATS::IO::NoRespondersError
|
268
|
+
raise JetStream::Error::ServiceUnavailable
|
269
|
+
end
|
268
270
|
|
269
271
|
result = if params[:direct]
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
if result.is_a?(Hash)
|
272
|
+
msg
|
273
|
+
else
|
274
|
+
JSON.parse(msg.data, symbolize_names: true)
|
275
|
+
end
|
276
|
+
if result.is_a?(Hash) && result[:error]
|
275
277
|
raise JS.from_error(result[:error])
|
276
278
|
end
|
277
279
|
|
@@ -279,21 +281,21 @@ module NATS
|
|
279
281
|
end
|
280
282
|
|
281
283
|
def _lift_msg_to_raw_msg(msg)
|
282
|
-
if msg.header
|
283
|
-
status = msg.header[
|
284
|
-
if status ==
|
284
|
+
if msg.header && msg.header["Status"]
|
285
|
+
status = msg.header["Status"]
|
286
|
+
if status == "404"
|
285
287
|
raise ::NATS::JetStream::Error::NotFound.new
|
286
288
|
else
|
287
289
|
raise JS.from_msg(msg)
|
288
290
|
end
|
289
291
|
end
|
290
|
-
subject = msg.header[
|
291
|
-
seq = msg.header[
|
292
|
+
subject = msg.header["Nats-Subject"]
|
293
|
+
seq = msg.header["Nats-Sequence"]
|
292
294
|
raw_msg = JetStream::API::RawStreamMsg.new(
|
293
295
|
subject: subject,
|
294
296
|
seq: seq,
|
295
|
-
headers: msg.header
|
296
|
-
|
297
|
+
headers: msg.header
|
298
|
+
)
|
297
299
|
raw_msg.data = msg.data
|
298
300
|
|
299
301
|
raw_msg
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -16,19 +18,21 @@ module NATS
|
|
16
18
|
class JetStream
|
17
19
|
module Msg
|
18
20
|
module Ack
|
21
|
+
# rubocop:disable Naming/ConstantName
|
22
|
+
|
19
23
|
# Ack types
|
20
|
-
Ack
|
21
|
-
Nak
|
22
|
-
Progress =
|
23
|
-
Term
|
24
|
+
Ack = "+ACK"
|
25
|
+
Nak = "-NAK"
|
26
|
+
Progress = "+WPI"
|
27
|
+
Term = "+TERM"
|
24
28
|
|
25
|
-
Empty =
|
26
|
-
DotSep =
|
27
|
-
NoDomainName =
|
29
|
+
Empty = ""
|
30
|
+
DotSep = "."
|
31
|
+
NoDomainName = "_"
|
28
32
|
|
29
33
|
# Position
|
30
|
-
Prefix0 =
|
31
|
-
Prefix1 =
|
34
|
+
Prefix0 = "$JS"
|
35
|
+
Prefix1 = "ACK"
|
32
36
|
Domain = 2
|
33
37
|
AccHash = 3
|
34
38
|
Stream = 4
|
@@ -50,6 +54,8 @@ module NATS
|
|
50
54
|
V2TokenCounts = 12
|
51
55
|
|
52
56
|
SequencePair = Struct.new(:stream, :consumer)
|
57
|
+
|
58
|
+
# rubocop:enable Naming/ConstantName
|
53
59
|
end
|
54
60
|
private_constant :Ack
|
55
61
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -20,10 +22,10 @@ module NATS
|
|
20
22
|
ensure_is_acked_once!
|
21
23
|
|
22
24
|
resp = if params[:timeout]
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
@nc.request(@reply, Ack::Ack, **params)
|
26
|
+
else
|
27
|
+
@nc.publish(@reply, Ack::Ack)
|
28
|
+
end
|
27
29
|
@sub.synchronize { @ackd = true }
|
28
30
|
|
29
31
|
resp
|
@@ -42,15 +44,15 @@ module NATS
|
|
42
44
|
def nak(**params)
|
43
45
|
ensure_is_acked_once!
|
44
46
|
payload = if params[:delay]
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
"#{Ack::Nak} #{{delay: params[:delay]}.to_json}"
|
48
|
+
else
|
49
|
+
Ack::Nak
|
50
|
+
end
|
49
51
|
resp = if params[:timeout]
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
@nc.request(@reply, payload, **params)
|
53
|
+
else
|
54
|
+
@nc.publish(@reply, payload)
|
55
|
+
end
|
54
56
|
@sub.synchronize { @ackd = true }
|
55
57
|
|
56
58
|
resp
|
@@ -60,10 +62,10 @@ module NATS
|
|
60
62
|
ensure_is_acked_once!
|
61
63
|
|
62
64
|
resp = if params[:timeout]
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
@nc.request(@reply, Ack::Term, **params)
|
66
|
+
else
|
67
|
+
@nc.publish(@reply, Ack::Term)
|
68
|
+
end
|
67
69
|
@sub.synchronize { @ackd = true }
|
68
70
|
|
69
71
|
resp
|
@@ -74,7 +76,7 @@ module NATS
|
|
74
76
|
end
|
75
77
|
|
76
78
|
def metadata
|
77
|
-
@meta ||= parse_metadata(reply)
|
79
|
+
@meta ||= parse_metadata(@reply)
|
78
80
|
end
|
79
81
|
|
80
82
|
private
|
@@ -88,18 +90,18 @@ module NATS
|
|
88
90
|
end
|
89
91
|
|
90
92
|
def parse_metadata(reply)
|
93
|
+
return unless reply && !reply.empty?
|
91
94
|
tokens = reply.split(Ack::DotSep)
|
92
95
|
n = tokens.count
|
93
96
|
|
94
|
-
|
95
|
-
when n < Ack::V1TokenCounts || (n > Ack::V1TokenCounts and n < Ack::V2TokenCounts)
|
97
|
+
if n < Ack::V1TokenCounts || ((n > Ack::V1TokenCounts) && (n < Ack::V2TokenCounts))
|
96
98
|
raise NotJSMessage.new("nats: not a jetstream message")
|
97
|
-
|
99
|
+
elsif tokens[0] != Ack::Prefix0 || tokens[1] != Ack::Prefix1
|
98
100
|
raise NotJSMessage.new("nats: not a jetstream message")
|
99
|
-
|
101
|
+
elsif n == Ack::V1TokenCounts
|
100
102
|
tokens.insert(Ack::Domain, Ack::Empty)
|
101
103
|
tokens.insert(Ack::AccHash, Ack::Empty)
|
102
|
-
|
104
|
+
elsif tokens[Ack::Domain] == Ack::NoDomainName
|
103
105
|
tokens[Ack::Domain] = Ack::Empty
|
104
106
|
end
|
105
107
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -12,7 +14,7 @@
|
|
12
14
|
# limitations under the License.
|
13
15
|
#
|
14
16
|
|
15
|
-
require
|
17
|
+
require "time"
|
16
18
|
|
17
19
|
module NATS
|
18
20
|
class JetStream
|
@@ -21,13 +23,13 @@ module NATS
|
|
21
23
|
attr_reader :sequence, :num_delivered, :num_pending, :timestamp, :stream, :consumer, :domain
|
22
24
|
|
23
25
|
def initialize(opts)
|
24
|
-
@sequence
|
25
|
-
@domain
|
26
|
+
@sequence = Ack::SequencePair.new(opts[Ack::StreamSeq].to_i, opts[Ack::ConsumerSeq].to_i)
|
27
|
+
@domain = opts[Ack::Domain]
|
26
28
|
@num_delivered = opts[Ack::NumDelivered].to_i
|
27
|
-
@num_pending
|
28
|
-
@timestamp
|
29
|
-
@stream
|
30
|
-
@consumer
|
29
|
+
@num_pending = opts[Ack::NumPending].to_i
|
30
|
+
@timestamp = Time.at((opts[Ack::Timestamp].to_i / 1_000_000_000.0))
|
31
|
+
@stream = opts[Ack::Stream]
|
32
|
+
@consumer = opts[Ack::Consumer]
|
31
33
|
# TODO: Not exposed in Go client either right now.
|
32
34
|
# account = opts[Ack::AccHash]
|
33
35
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -12,9 +14,9 @@
|
|
12
14
|
# limitations under the License.
|
13
15
|
#
|
14
16
|
|
15
|
-
require_relative
|
16
|
-
require_relative
|
17
|
-
require_relative
|
17
|
+
require_relative "msg/ack"
|
18
|
+
require_relative "msg/ack_methods"
|
19
|
+
require_relative "msg/metadata"
|
18
20
|
|
19
21
|
module NATS
|
20
22
|
class JetStream
|
@@ -23,4 +25,9 @@ module NATS
|
|
23
25
|
module Msg
|
24
26
|
end
|
25
27
|
end
|
26
|
-
|
28
|
+
|
29
|
+
class Msg
|
30
|
+
# Enhance it with ack related methods from JetStream to ack msgs.
|
31
|
+
include JetStream::Msg::AckMethods
|
32
|
+
end
|
33
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -12,7 +14,7 @@
|
|
12
14
|
# limitations under the License.
|
13
15
|
#
|
14
16
|
|
15
|
-
require_relative
|
17
|
+
require_relative "errors"
|
16
18
|
|
17
19
|
module NATS
|
18
20
|
class JetStream
|
@@ -39,7 +41,7 @@ module NATS
|
|
39
41
|
module PullSubscription
|
40
42
|
# next_msg is not available for pull based subscriptions.
|
41
43
|
# @raise [NATS::JetStream::Error]
|
42
|
-
def next_msg(params={})
|
44
|
+
def next_msg(params = {})
|
43
45
|
raise ::NATS::JetStream::Error.new("nats: pull subscription cannot use next_msg")
|
44
46
|
end
|
45
47
|
|
@@ -49,7 +51,7 @@ module NATS
|
|
49
51
|
# @param params [Hash] Options to customize the fetch request.
|
50
52
|
# @option params [Float] :timeout Duration of the fetch request before it expires.
|
51
53
|
# @return [Array<NATS::Msg>]
|
52
|
-
def fetch(batch=1, params={})
|
54
|
+
def fetch(batch = 1, params = {})
|
53
55
|
if batch < 1
|
54
56
|
raise ::NATS::JetStream::Error.new("nats: invalid batch size")
|
55
57
|
end
|
@@ -80,7 +82,7 @@ module NATS
|
|
80
82
|
if JS.is_status_msg(msg)
|
81
83
|
case msg.header["Status"]
|
82
84
|
when JS::Status::NoMsgs
|
83
|
-
|
85
|
+
nil
|
84
86
|
when JS::Status::RequestTimeout
|
85
87
|
# Skip
|
86
88
|
else
|
@@ -193,27 +195,31 @@ module NATS
|
|
193
195
|
|
194
196
|
# Check if have not received yet a single message.
|
195
197
|
duration = MonotonicTime.since(start_time)
|
196
|
-
|
198
|
+
|
199
|
+
if msgs.empty? && (duration > timeout)
|
197
200
|
raise NATS::Timeout.new("nats: fetch timeout")
|
198
201
|
end
|
199
202
|
|
200
203
|
needed = batch - msgs.count
|
201
|
-
while needed > 0
|
204
|
+
while (needed > 0) && (MonotonicTime.since(start_time) < timeout)
|
202
205
|
duration = MonotonicTime.since(start_time)
|
203
206
|
|
204
207
|
# Wait for the rest of the messages.
|
205
208
|
synchronize do
|
206
|
-
|
207
209
|
# Wait until there is a message delivered.
|
208
210
|
if @pending_queue.empty?
|
209
211
|
deadline = timeout - duration
|
212
|
+
MonotonicTime.now
|
213
|
+
|
210
214
|
wait_for_msgs_cond.wait(deadline) if deadline > 0
|
211
215
|
|
212
216
|
duration = MonotonicTime.since(start_time)
|
213
|
-
if msgs.empty? && @pending_queue.empty?
|
217
|
+
if msgs.empty? && @pending_queue.empty? && (duration > timeout)
|
214
218
|
raise NATS::Timeout.new("nats: fetch timeout")
|
215
219
|
end
|
216
|
-
|
220
|
+
end
|
221
|
+
|
222
|
+
unless @pending_queue.empty?
|
217
223
|
msg = @pending_queue.pop
|
218
224
|
@pending_size -= msg.data.size
|
219
225
|
|
@@ -244,6 +250,11 @@ module NATS
|
|
244
250
|
end
|
245
251
|
end
|
246
252
|
|
253
|
+
# Check if timed out waiting for messages.
|
254
|
+
if msgs.empty? && (MonotonicTime.since(start_time) > timeout)
|
255
|
+
raise NATS::Timeout.new("nats: fetch timeout")
|
256
|
+
end
|
257
|
+
|
247
258
|
msgs
|
248
259
|
end
|
249
260
|
|
@@ -251,7 +262,7 @@ module NATS
|
|
251
262
|
# @param params [Hash] Options to customize API request.
|
252
263
|
# @option params [Float] :timeout Time to wait for response.
|
253
264
|
# @return [JetStream::API::ConsumerInfo] The latest ConsumerInfo of the consumer.
|
254
|
-
def consumer_info(params={})
|
265
|
+
def consumer_info(params = {})
|
255
266
|
@jsi.js.consumer_info(@jsi.stream, @jsi.consumer, params)
|
256
267
|
end
|
257
268
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -33,7 +35,7 @@ module NATS
|
|
33
35
|
# @param params [Hash] Options to customize API request.
|
34
36
|
# @option params [Float] :timeout Time to wait for response.
|
35
37
|
# @return [JetStream::API::ConsumerInfo] The latest ConsumerInfo of the consumer.
|
36
|
-
def consumer_info(params={})
|
38
|
+
def consumer_info(params = {})
|
37
39
|
@jsi.js.consumer_info(@jsi.stream, @jsi.consumer, params)
|
38
40
|
end
|
39
41
|
end
|