nats-pure 2.2.0 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nats/io/client.rb +11 -7
- data/lib/nats/io/jetstream/api.rb +305 -0
- data/lib/nats/io/jetstream/errors.rb +104 -0
- data/lib/nats/io/jetstream/js/config.rb +26 -0
- data/lib/nats/io/jetstream/js/header.rb +31 -0
- data/lib/nats/io/jetstream/js/status.rb +27 -0
- data/lib/nats/io/jetstream/js/sub.rb +30 -0
- data/lib/nats/io/jetstream/js.rb +93 -0
- data/lib/nats/io/jetstream/manager.rb +284 -0
- data/lib/nats/io/jetstream/msg/ack.rb +57 -0
- data/lib/nats/io/jetstream/msg/ack_methods.rb +107 -0
- data/lib/nats/io/jetstream/msg/metadata.rb +37 -0
- data/lib/nats/io/jetstream/msg.rb +26 -0
- data/lib/nats/io/jetstream/pull_subscription.rb +260 -0
- data/lib/nats/io/jetstream/push_subscription.rb +42 -0
- data/lib/nats/io/jetstream.rb +269 -0
- data/lib/nats/io/kv/api.rb +39 -0
- data/lib/nats/io/kv/bucket_status.rb +38 -0
- data/lib/nats/io/kv/errors.rb +60 -0
- data/lib/nats/io/kv/manager.rb +89 -0
- data/lib/nats/io/kv.rb +5 -157
- data/lib/nats/io/msg.rb +1 -1
- data/lib/nats/io/version.rb +1 -1
- metadata +21 -3
- data/lib/nats/io/js.rb +0 -1434
@@ -0,0 +1,284 @@
|
|
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
|
+
# A JetStream::Manager can be used to make requests to the JetStream API.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# require 'nats/client'
|
21
|
+
#
|
22
|
+
# nc = NATS.connect("demo.nats.io")
|
23
|
+
#
|
24
|
+
# config = JetStream::API::StreamConfig.new()
|
25
|
+
# nc.jsm.add_stream(config)
|
26
|
+
#
|
27
|
+
#
|
28
|
+
module Manager
|
29
|
+
# add_stream creates a stream with a given config.
|
30
|
+
# @param config [JetStream::API::StreamConfig] Configuration of the stream to create.
|
31
|
+
# @param params [Hash] Options to customize API request.
|
32
|
+
# @option params [Float] :timeout Time to wait for response.
|
33
|
+
# @return [JetStream::API::StreamCreateResponse] The result of creating a Stream.
|
34
|
+
def add_stream(config, params={})
|
35
|
+
config = if not config.is_a?(JetStream::API::StreamConfig)
|
36
|
+
JetStream::API::StreamConfig.new(config)
|
37
|
+
else
|
38
|
+
config
|
39
|
+
end
|
40
|
+
stream = config[:name]
|
41
|
+
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|\.|\>|\*)/
|
43
|
+
req_subject = "#{@prefix}.STREAM.CREATE.#{stream}"
|
44
|
+
|
45
|
+
cfg = config.to_h.compact
|
46
|
+
result = api_request(req_subject, cfg.to_json, params)
|
47
|
+
JetStream::API::StreamCreateResponse.new(result)
|
48
|
+
end
|
49
|
+
|
50
|
+
# stream_info retrieves the current status of a stream.
|
51
|
+
# @param stream [String] Name of the stream.
|
52
|
+
# @param params [Hash] Options to customize API request.
|
53
|
+
# @option params [Float] :timeout Time to wait for response.
|
54
|
+
# @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? or stream.empty?
|
57
|
+
|
58
|
+
req_subject = "#{@prefix}.STREAM.INFO.#{stream}"
|
59
|
+
result = api_request(req_subject, '', params)
|
60
|
+
JetStream::API::StreamInfo.new(result)
|
61
|
+
end
|
62
|
+
|
63
|
+
# update_stream edits an existed stream with a given config.
|
64
|
+
# @param config [JetStream::API::StreamConfig] Configuration of the stream to create.
|
65
|
+
# @param params [Hash] Options to customize API request.
|
66
|
+
# @option params [Float] :timeout Time to wait for response.
|
67
|
+
# @return [JetStream::API::StreamCreateResponse] The result of creating a Stream.
|
68
|
+
def update_stream(config, params={})
|
69
|
+
config = if not config.is_a?(JetStream::API::StreamConfig)
|
70
|
+
JetStream::API::StreamConfig.new(config)
|
71
|
+
else
|
72
|
+
config
|
73
|
+
end
|
74
|
+
stream = config[:name]
|
75
|
+
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|\.|\>|\*)/
|
77
|
+
req_subject = "#{@prefix}.STREAM.UPDATE.#{stream}"
|
78
|
+
cfg = config.to_h.compact
|
79
|
+
result = api_request(req_subject, cfg.to_json, params)
|
80
|
+
JetStream::API::StreamCreateResponse.new(result)
|
81
|
+
end
|
82
|
+
|
83
|
+
# delete_stream deletes a stream.
|
84
|
+
# @param stream [String] Name of the stream.
|
85
|
+
# @param params [Hash] Options to customize API request.
|
86
|
+
# @option params [Float] :timeout Time to wait for response.
|
87
|
+
# @return [Boolean]
|
88
|
+
def delete_stream(stream, params={})
|
89
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? or stream.empty?
|
90
|
+
|
91
|
+
req_subject = "#{@prefix}.STREAM.DELETE.#{stream}"
|
92
|
+
result = api_request(req_subject, '', params)
|
93
|
+
result[:success]
|
94
|
+
end
|
95
|
+
|
96
|
+
# add_consumer creates a consumer with a given config.
|
97
|
+
# @param stream [String] Name of the stream.
|
98
|
+
# @param config [JetStream::API::ConsumerConfig] Configuration of the consumer to create.
|
99
|
+
# @param params [Hash] Options to customize API request.
|
100
|
+
# @option params [Float] :timeout Time to wait for response.
|
101
|
+
# @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? or stream.empty?
|
104
|
+
config = if not config.is_a?(JetStream::API::ConsumerConfig)
|
105
|
+
JetStream::API::ConsumerConfig.new(config)
|
106
|
+
else
|
107
|
+
config
|
108
|
+
end
|
109
|
+
|
110
|
+
req_subject = case
|
111
|
+
when config[:name]
|
112
|
+
# NOTE: Only supported after nats-server v2.9.0
|
113
|
+
if config[:filter_subject] && config[:filter_subject] != ">"
|
114
|
+
"#{@prefix}.CONSUMER.CREATE.#{stream}.#{config[:name]}.#{config[:filter_subject]}"
|
115
|
+
else
|
116
|
+
"#{@prefix}.CONSUMER.CREATE.#{stream}.#{config[:name]}"
|
117
|
+
end
|
118
|
+
when config[:durable_name]
|
119
|
+
"#{@prefix}.CONSUMER.DURABLE.CREATE.#{stream}.#{config[:durable_name]}"
|
120
|
+
else
|
121
|
+
"#{@prefix}.CONSUMER.CREATE.#{stream}"
|
122
|
+
end
|
123
|
+
|
124
|
+
config[:ack_policy] ||= JS::Config::AckExplicit
|
125
|
+
# Check if have to normalize ack wait so that it is in nanoseconds for Go compat.
|
126
|
+
if config[:ack_wait]
|
127
|
+
raise ArgumentError.new("nats: invalid ack wait") unless config[:ack_wait].is_a?(Integer)
|
128
|
+
config[:ack_wait] = config[:ack_wait] * ::NATS::NANOSECONDS
|
129
|
+
end
|
130
|
+
if config[:inactive_threshold]
|
131
|
+
raise ArgumentError.new("nats: invalid inactive threshold") unless config[:inactive_threshold].is_a?(Integer)
|
132
|
+
config[:inactive_threshold] = config[:inactive_threshold] * ::NATS::NANOSECONDS
|
133
|
+
end
|
134
|
+
|
135
|
+
cfg = config.to_h.compact
|
136
|
+
req = {
|
137
|
+
stream_name: stream,
|
138
|
+
config: cfg
|
139
|
+
}
|
140
|
+
|
141
|
+
result = api_request(req_subject, req.to_json, params)
|
142
|
+
JetStream::API::ConsumerInfo.new(result).freeze
|
143
|
+
end
|
144
|
+
|
145
|
+
# consumer_info retrieves the current status of a consumer.
|
146
|
+
# @param stream [String] Name of the stream.
|
147
|
+
# @param consumer [String] Name of the consumer.
|
148
|
+
# @param params [Hash] Options to customize API request.
|
149
|
+
# @option params [Float] :timeout Time to wait for response.
|
150
|
+
# @return [JetStream::API::ConsumerInfo] The latest ConsumerInfo of the consumer.
|
151
|
+
def consumer_info(stream, consumer, params={})
|
152
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? or stream.empty?
|
153
|
+
raise JetStream::Error::InvalidConsumerName.new("nats: invalid consumer name") if consumer.nil? or consumer.empty?
|
154
|
+
|
155
|
+
req_subject = "#{@prefix}.CONSUMER.INFO.#{stream}.#{consumer}"
|
156
|
+
result = api_request(req_subject, '', params)
|
157
|
+
JetStream::API::ConsumerInfo.new(result)
|
158
|
+
end
|
159
|
+
|
160
|
+
# delete_consumer deletes a consumer.
|
161
|
+
# @param stream [String] Name of the stream.
|
162
|
+
# @param consumer [String] Name of the consumer.
|
163
|
+
# @param params [Hash] Options to customize API request.
|
164
|
+
# @option params [Float] :timeout Time to wait for response.
|
165
|
+
# @return [Boolean]
|
166
|
+
def delete_consumer(stream, consumer, params={})
|
167
|
+
raise JetStream::Error::InvalidStreamName.new("nats: invalid stream name") if stream.nil? or stream.empty?
|
168
|
+
raise JetStream::Error::InvalidConsumerName.new("nats: invalid consumer name") if consumer.nil? or consumer.empty?
|
169
|
+
|
170
|
+
req_subject = "#{@prefix}.CONSUMER.DELETE.#{stream}.#{consumer}"
|
171
|
+
result = api_request(req_subject, '', params)
|
172
|
+
result[:success]
|
173
|
+
end
|
174
|
+
|
175
|
+
# find_stream_name_by_subject does a lookup for the stream to which
|
176
|
+
# the subject belongs.
|
177
|
+
# @param subject [String] The subject that belongs to a stream.
|
178
|
+
# @param params [Hash] Options to customize API request.
|
179
|
+
# @option params [Float] :timeout Time to wait for response.
|
180
|
+
# @return [String] The name of the JetStream stream for the subject.
|
181
|
+
def find_stream_name_by_subject(subject, params={})
|
182
|
+
req_subject = "#{@prefix}.STREAM.NAMES"
|
183
|
+
req = { subject: subject }
|
184
|
+
result = api_request(req_subject, req.to_json, params)
|
185
|
+
raise JetStream::Error::NotFound unless result[:streams]
|
186
|
+
|
187
|
+
result[:streams].first
|
188
|
+
end
|
189
|
+
|
190
|
+
# get_msg retrieves a message from the stream.
|
191
|
+
# @param stream_name [String] The stream_name.
|
192
|
+
# @param params [Hash] Options to customize API request.
|
193
|
+
# @option next [Boolean] Fetch the next message for a subject.
|
194
|
+
# @option seq [Integer] Sequence number of a message.
|
195
|
+
# @option subject [String] Subject of the message.
|
196
|
+
# @option direct [Boolean] Use direct mode to for faster access (requires NATS v2.9.0)
|
197
|
+
def get_msg(stream_name, params={})
|
198
|
+
req = {}
|
199
|
+
case
|
200
|
+
when params[:next]
|
201
|
+
req[:seq] = params[:seq]
|
202
|
+
req[:next_by_subj] = params[:subject]
|
203
|
+
when params[:seq]
|
204
|
+
req[:seq] = params[:seq]
|
205
|
+
when params[:subject]
|
206
|
+
req[:last_by_subj] = params[:subject]
|
207
|
+
end
|
208
|
+
|
209
|
+
data = req.to_json
|
210
|
+
if params[:direct]
|
211
|
+
if params[:subject] and not params[:seq]
|
212
|
+
# last_by_subject type request requires no payload.
|
213
|
+
data = ''
|
214
|
+
req_subject = "#{@prefix}.DIRECT.GET.#{stream_name}.#{params[:subject]}"
|
215
|
+
else
|
216
|
+
req_subject = "#{@prefix}.DIRECT.GET.#{stream_name}"
|
217
|
+
end
|
218
|
+
else
|
219
|
+
req_subject = "#{@prefix}.STREAM.MSG.GET.#{stream_name}"
|
220
|
+
end
|
221
|
+
resp = api_request(req_subject, data, direct: params[:direct])
|
222
|
+
msg = if params[:direct]
|
223
|
+
_lift_msg_to_raw_msg(resp)
|
224
|
+
else
|
225
|
+
JetStream::API::RawStreamMsg.new(resp[:message])
|
226
|
+
end
|
227
|
+
|
228
|
+
msg
|
229
|
+
end
|
230
|
+
|
231
|
+
def get_last_msg(stream_name, subject, params={})
|
232
|
+
params[:subject] = subject
|
233
|
+
get_msg(stream_name, params)
|
234
|
+
end
|
235
|
+
|
236
|
+
def account_info
|
237
|
+
api_request("#{@prefix}.INFO")
|
238
|
+
end
|
239
|
+
|
240
|
+
private
|
241
|
+
|
242
|
+
def api_request(req_subject, req="", params={})
|
243
|
+
params[:timeout] ||= @opts[:timeout]
|
244
|
+
msg = begin
|
245
|
+
@nc.request(req_subject, req, **params)
|
246
|
+
rescue NATS::IO::NoRespondersError
|
247
|
+
raise JetStream::Error::ServiceUnavailable
|
248
|
+
end
|
249
|
+
|
250
|
+
result = if params[:direct]
|
251
|
+
msg
|
252
|
+
else
|
253
|
+
JSON.parse(msg.data, symbolize_names: true)
|
254
|
+
end
|
255
|
+
if result.is_a?(Hash) and result[:error]
|
256
|
+
raise JS.from_error(result[:error])
|
257
|
+
end
|
258
|
+
|
259
|
+
result
|
260
|
+
end
|
261
|
+
|
262
|
+
def _lift_msg_to_raw_msg(msg)
|
263
|
+
if msg.header and msg.header['Status']
|
264
|
+
status = msg.header['Status']
|
265
|
+
if status == '404'
|
266
|
+
raise ::NATS::JetStream::Error::NotFound.new
|
267
|
+
else
|
268
|
+
raise JS.from_msg(msg)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
subject = msg.header['Nats-Subject']
|
272
|
+
seq = msg.header['Nats-Sequence']
|
273
|
+
raw_msg = JetStream::API::RawStreamMsg.new(
|
274
|
+
subject: subject,
|
275
|
+
seq: seq,
|
276
|
+
headers: msg.header,
|
277
|
+
)
|
278
|
+
raw_msg.data = msg.data
|
279
|
+
|
280
|
+
raw_msg
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
@@ -0,0 +1,57 @@
|
|
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 Msg
|
18
|
+
module Ack
|
19
|
+
# Ack types
|
20
|
+
Ack = ("+ACK".freeze)
|
21
|
+
Nak = ("-NAK".freeze)
|
22
|
+
Progress = ("+WPI".freeze)
|
23
|
+
Term = ("+TERM".freeze)
|
24
|
+
|
25
|
+
Empty = (''.freeze)
|
26
|
+
DotSep = ('.'.freeze)
|
27
|
+
NoDomainName = ('_'.freeze)
|
28
|
+
|
29
|
+
# Position
|
30
|
+
Prefix0 = ('$JS'.freeze)
|
31
|
+
Prefix1 = ('ACK'.freeze)
|
32
|
+
Domain = 2
|
33
|
+
AccHash = 3
|
34
|
+
Stream = 4
|
35
|
+
Consumer = 5
|
36
|
+
NumDelivered = 6
|
37
|
+
StreamSeq = 7
|
38
|
+
ConsumerSeq = 8
|
39
|
+
Timestamp = 9
|
40
|
+
NumPending = 10
|
41
|
+
|
42
|
+
# Subject without domain:
|
43
|
+
# $JS.ACK.<stream>.<consumer>.<delivered>.<sseq>.<cseq>.<tm>.<pending>
|
44
|
+
#
|
45
|
+
V1TokenCounts = 9
|
46
|
+
|
47
|
+
# Subject with domain:
|
48
|
+
# $JS.ACK.<domain>.<account hash>.<stream>.<consumer>.<delivered>.<sseq>.<cseq>.<tm>.<pending>.<a token with a random value>
|
49
|
+
#
|
50
|
+
V2TokenCounts = 12
|
51
|
+
|
52
|
+
SequencePair = Struct.new(:stream, :consumer)
|
53
|
+
end
|
54
|
+
private_constant :Ack
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,107 @@
|
|
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 Msg
|
18
|
+
module AckMethods
|
19
|
+
def ack(**params)
|
20
|
+
ensure_is_acked_once!
|
21
|
+
|
22
|
+
resp = if params[:timeout]
|
23
|
+
@nc.request(@reply, Ack::Ack, **params)
|
24
|
+
else
|
25
|
+
@nc.publish(@reply, Ack::Ack)
|
26
|
+
end
|
27
|
+
@sub.synchronize { @ackd = true }
|
28
|
+
|
29
|
+
resp
|
30
|
+
end
|
31
|
+
|
32
|
+
def ack_sync(**params)
|
33
|
+
ensure_is_acked_once!
|
34
|
+
|
35
|
+
params[:timeout] ||= 0.5
|
36
|
+
resp = @nc.request(@reply, Ack::Ack, **params)
|
37
|
+
@sub.synchronize { @ackd = true }
|
38
|
+
|
39
|
+
resp
|
40
|
+
end
|
41
|
+
|
42
|
+
def nak(**params)
|
43
|
+
ensure_is_acked_once!
|
44
|
+
|
45
|
+
resp = if params[:timeout]
|
46
|
+
@nc.request(@reply, Ack::Nak, **params)
|
47
|
+
else
|
48
|
+
@nc.publish(@reply, Ack::Nak)
|
49
|
+
end
|
50
|
+
@sub.synchronize { @ackd = true }
|
51
|
+
|
52
|
+
resp
|
53
|
+
end
|
54
|
+
|
55
|
+
def term(**params)
|
56
|
+
ensure_is_acked_once!
|
57
|
+
|
58
|
+
resp = if params[:timeout]
|
59
|
+
@nc.request(@reply, Ack::Term, **params)
|
60
|
+
else
|
61
|
+
@nc.publish(@reply, Ack::Term)
|
62
|
+
end
|
63
|
+
@sub.synchronize { @ackd = true }
|
64
|
+
|
65
|
+
resp
|
66
|
+
end
|
67
|
+
|
68
|
+
def in_progress(**params)
|
69
|
+
params[:timeout] ? @nc.request(@reply, Ack::Progress, **params) : @nc.publish(@reply, Ack::Progress)
|
70
|
+
end
|
71
|
+
|
72
|
+
def metadata
|
73
|
+
@meta ||= parse_metadata(reply)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def ensure_is_acked_once!
|
79
|
+
@sub.synchronize do
|
80
|
+
if @ackd
|
81
|
+
raise JetStream::Error::MsgAlreadyAckd.new("nats: message was already acknowledged: #{self}")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_metadata(reply)
|
87
|
+
tokens = reply.split(Ack::DotSep)
|
88
|
+
n = tokens.count
|
89
|
+
|
90
|
+
case
|
91
|
+
when n < Ack::V1TokenCounts || (n > Ack::V1TokenCounts and n < Ack::V2TokenCounts)
|
92
|
+
raise NotJSMessage.new("nats: not a jetstream message")
|
93
|
+
when tokens[0] != Ack::Prefix0 || tokens[1] != Ack::Prefix1
|
94
|
+
raise NotJSMessage.new("nats: not a jetstream message")
|
95
|
+
when n == Ack::V1TokenCounts
|
96
|
+
tokens.insert(Ack::Domain, Ack::Empty)
|
97
|
+
tokens.insert(Ack::AccHash, Ack::Empty)
|
98
|
+
when tokens[Ack::Domain] == Ack::NoDomainName
|
99
|
+
tokens[Ack::Domain] = Ack::Empty
|
100
|
+
end
|
101
|
+
|
102
|
+
Metadata.new(tokens)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,37 @@
|
|
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 'time'
|
16
|
+
|
17
|
+
module NATS
|
18
|
+
class JetStream
|
19
|
+
module Msg
|
20
|
+
class Metadata
|
21
|
+
attr_reader :sequence, :num_delivered, :num_pending, :timestamp, :stream, :consumer, :domain
|
22
|
+
|
23
|
+
def initialize(opts)
|
24
|
+
@sequence = Ack::SequencePair.new(opts[Ack::StreamSeq].to_i, opts[Ack::ConsumerSeq].to_i)
|
25
|
+
@domain = opts[Ack::Domain]
|
26
|
+
@num_delivered = opts[Ack::NumDelivered].to_i
|
27
|
+
@num_pending = opts[Ack::NumPending].to_i
|
28
|
+
@timestamp = Time.at((opts[Ack::Timestamp].to_i / 1_000_000_000.0))
|
29
|
+
@stream = opts[Ack::Stream]
|
30
|
+
@consumer = opts[Ack::Consumer]
|
31
|
+
# TODO: Not exposed in Go client either right now.
|
32
|
+
# account = opts[Ack::AccHash]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
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
|
+
require_relative 'msg/ack'
|
16
|
+
require_relative 'msg/ack_methods'
|
17
|
+
require_relative 'msg/metadata'
|
18
|
+
|
19
|
+
module NATS
|
20
|
+
class JetStream
|
21
|
+
# JetStream::Msg module includes the methods so that a regular NATS::Msg
|
22
|
+
# can be enhanced with JetStream features like acking and metadata.
|
23
|
+
module Msg
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|