nats-pure 2.3.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/README.md +10 -3
  4. data/lib/nats/client.rb +7 -2
  5. data/lib/nats/io/client.rb +304 -282
  6. data/lib/nats/io/errors.rb +2 -0
  7. data/lib/nats/io/jetstream/api.rb +54 -47
  8. data/lib/nats/io/jetstream/errors.rb +30 -14
  9. data/lib/nats/io/jetstream/js/config.rb +9 -3
  10. data/lib/nats/io/jetstream/js/header.rb +15 -9
  11. data/lib/nats/io/jetstream/js/status.rb +11 -5
  12. data/lib/nats/io/jetstream/js/sub.rb +4 -2
  13. data/lib/nats/io/jetstream/js.rb +10 -8
  14. data/lib/nats/io/jetstream/manager.rb +104 -83
  15. data/lib/nats/io/jetstream/msg/ack.rb +15 -9
  16. data/lib/nats/io/jetstream/msg/ack_methods.rb +24 -22
  17. data/lib/nats/io/jetstream/msg/metadata.rb +9 -7
  18. data/lib/nats/io/jetstream/msg.rb +11 -4
  19. data/lib/nats/io/jetstream/pull_subscription.rb +21 -10
  20. data/lib/nats/io/jetstream/push_subscription.rb +3 -1
  21. data/lib/nats/io/jetstream.rb +125 -54
  22. data/lib/nats/io/kv/api.rb +7 -3
  23. data/lib/nats/io/kv/bucket_status.rb +7 -5
  24. data/lib/nats/io/kv/errors.rb +25 -2
  25. data/lib/nats/io/kv/manager.rb +19 -10
  26. data/lib/nats/io/kv.rb +359 -22
  27. data/lib/nats/io/msg.rb +19 -19
  28. data/lib/nats/io/parser.rb +23 -23
  29. data/lib/nats/io/rails.rb +2 -0
  30. data/lib/nats/io/subscription.rb +25 -22
  31. data/lib/nats/io/version.rb +4 -2
  32. data/lib/nats/io/websocket.rb +10 -8
  33. data/lib/nats/nuid.rb +33 -22
  34. data/lib/nats/service/callbacks.rb +22 -0
  35. data/lib/nats/service/endpoint.rb +155 -0
  36. data/lib/nats/service/errors.rb +44 -0
  37. data/lib/nats/service/group.rb +37 -0
  38. data/lib/nats/service/monitoring.rb +108 -0
  39. data/lib/nats/service/stats.rb +52 -0
  40. data/lib/nats/service/status.rb +66 -0
  41. data/lib/nats/service/validator.rb +31 -0
  42. data/lib/nats/service.rb +121 -0
  43. data/lib/nats/utils/list.rb +26 -0
  44. data/lib/nats-pure.rb +5 -0
  45. data/lib/nats.rb +10 -6
  46. 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 not config.is_a?(JetStream::API::StreamConfig)
36
- JetStream::API::StreamConfig.new(config)
37
- else
38
- config
39
- end
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? or stream.empty?
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, '', params)
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 not config.is_a?(JetStream::API::StreamConfig)
70
- JetStream::API::StreamConfig.new(config)
71
- else
72
- config
73
- end
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? or stream.empty?
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, '', params)
94
+ result = api_request(req_subject, "", params)
93
95
  result[:success]
94
96
  end
95
97
 
@@ -99,27 +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? 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
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
111
+ config[:name] ||= config[:durable_name]
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
123
143
 
124
144
  config[:ack_policy] ||= JS::Config::AckExplicit
125
145
  # Check if have to normalize ack wait so that it is in nanoseconds for Go compat.
@@ -131,6 +151,10 @@ module NATS
131
151
  raise ArgumentError.new("nats: invalid inactive threshold") unless config[:inactive_threshold].is_a?(Integer)
132
152
  config[:inactive_threshold] = config[:inactive_threshold] * ::NATS::NANOSECONDS
133
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
134
158
 
135
159
  cfg = config.to_h.compact
136
160
  req = {
@@ -148,12 +172,12 @@ module NATS
148
172
  # @param params [Hash] Options to customize API request.
149
173
  # @option params [Float] :timeout Time to wait for response.
150
174
  # @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?
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?
154
178
 
155
179
  req_subject = "#{@prefix}.CONSUMER.INFO.#{stream}.#{consumer}"
156
- result = api_request(req_subject, '', params)
180
+ result = api_request(req_subject, "", params)
157
181
  JetStream::API::ConsumerInfo.new(result)
158
182
  end
159
183
 
@@ -163,12 +187,12 @@ module NATS
163
187
  # @param params [Hash] Options to customize API request.
164
188
  # @option params [Float] :timeout Time to wait for response.
165
189
  # @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?
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?
169
193
 
170
194
  req_subject = "#{@prefix}.CONSUMER.DELETE.#{stream}.#{consumer}"
171
- result = api_request(req_subject, '', params)
195
+ result = api_request(req_subject, "", params)
172
196
  result[:success]
173
197
  end
174
198
 
@@ -178,9 +202,9 @@ module NATS
178
202
  # @param params [Hash] Options to customize API request.
179
203
  # @option params [Float] :timeout Time to wait for response.
180
204
  # @return [String] The name of the JetStream stream for the subject.
181
- def find_stream_name_by_subject(subject, params={})
205
+ def find_stream_name_by_subject(subject, params = {})
182
206
  req_subject = "#{@prefix}.STREAM.NAMES"
183
- req = { subject: subject }
207
+ req = {subject: subject}
184
208
  result = api_request(req_subject, req.to_json, params)
185
209
  raise JetStream::Error::NotFound unless result[:streams]
186
210
 
@@ -194,23 +218,22 @@ module NATS
194
218
  # @option seq [Integer] Sequence number of a message.
195
219
  # @option subject [String] Subject of the message.
196
220
  # @option direct [Boolean] Use direct mode to for faster access (requires NATS v2.9.0)
197
- def get_msg(stream_name, params={})
221
+ def get_msg(stream_name, params = {})
198
222
  req = {}
199
- case
200
- when params[:next]
223
+ if params[:next]
201
224
  req[:seq] = params[:seq]
202
225
  req[:next_by_subj] = params[:subject]
203
- when params[:seq]
226
+ elsif params[:seq]
204
227
  req[:seq] = params[:seq]
205
- when params[:subject]
228
+ elsif params[:subject]
206
229
  req[:last_by_subj] = params[:subject]
207
230
  end
208
231
 
209
232
  data = req.to_json
210
233
  if params[:direct]
211
- if params[:subject] and not params[:seq]
234
+ if params[:subject] && !(params[:seq])
212
235
  # last_by_subject type request requires no payload.
213
- data = ''
236
+ data = ""
214
237
  req_subject = "#{@prefix}.DIRECT.GET.#{stream_name}.#{params[:subject]}"
215
238
  else
216
239
  req_subject = "#{@prefix}.DIRECT.GET.#{stream_name}"
@@ -219,16 +242,14 @@ module NATS
219
242
  req_subject = "#{@prefix}.STREAM.MSG.GET.#{stream_name}"
220
243
  end
221
244
  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
245
+ if params[:direct]
246
+ _lift_msg_to_raw_msg(resp)
247
+ else
248
+ JetStream::API::RawStreamMsg.new(resp[:message])
249
+ end
229
250
  end
230
251
 
231
- def get_last_msg(stream_name, subject, params={})
252
+ def get_last_msg(stream_name, subject, params = {})
232
253
  params[:subject] = subject
233
254
  get_msg(stream_name, params)
234
255
  end
@@ -239,20 +260,20 @@ module NATS
239
260
 
240
261
  private
241
262
 
242
- def api_request(req_subject, req="", params={})
263
+ def api_request(req_subject, req = "", params = {})
243
264
  params[:timeout] ||= @opts[:timeout]
244
265
  msg = begin
245
- @nc.request(req_subject, req, **params)
246
- rescue NATS::IO::NoRespondersError
247
- raise JetStream::Error::ServiceUnavailable
248
- end
266
+ @nc.request(req_subject, req, **params)
267
+ rescue NATS::IO::NoRespondersError
268
+ raise JetStream::Error::ServiceUnavailable
269
+ end
249
270
 
250
271
  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]
272
+ msg
273
+ else
274
+ JSON.parse(msg.data, symbolize_names: true)
275
+ end
276
+ if result.is_a?(Hash) && result[:error]
256
277
  raise JS.from_error(result[:error])
257
278
  end
258
279
 
@@ -260,21 +281,21 @@ module NATS
260
281
  end
261
282
 
262
283
  def _lift_msg_to_raw_msg(msg)
263
- if msg.header and msg.header['Status']
264
- status = msg.header['Status']
265
- if status == '404'
284
+ if msg.header && msg.header["Status"]
285
+ status = msg.header["Status"]
286
+ if status == "404"
266
287
  raise ::NATS::JetStream::Error::NotFound.new
267
288
  else
268
289
  raise JS.from_msg(msg)
269
290
  end
270
291
  end
271
- subject = msg.header['Nats-Subject']
272
- seq = msg.header['Nats-Sequence']
292
+ subject = msg.header["Nats-Subject"]
293
+ seq = msg.header["Nats-Sequence"]
273
294
  raw_msg = JetStream::API::RawStreamMsg.new(
274
295
  subject: subject,
275
296
  seq: seq,
276
- headers: msg.header,
277
- )
297
+ headers: msg.header
298
+ )
278
299
  raw_msg.data = msg.data
279
300
 
280
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 = ("+ACK".freeze)
21
- Nak = ("-NAK".freeze)
22
- Progress = ("+WPI".freeze)
23
- Term = ("+TERM".freeze)
24
+ Ack = "+ACK"
25
+ Nak = "-NAK"
26
+ Progress = "+WPI"
27
+ Term = "+TERM"
24
28
 
25
- Empty = (''.freeze)
26
- DotSep = ('.'.freeze)
27
- NoDomainName = ('_'.freeze)
29
+ Empty = ""
30
+ DotSep = "."
31
+ NoDomainName = "_"
28
32
 
29
33
  # Position
30
- Prefix0 = ('$JS'.freeze)
31
- Prefix1 = ('ACK'.freeze)
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
- @nc.request(@reply, Ack::Ack, **params)
24
- else
25
- @nc.publish(@reply, Ack::Ack)
26
- end
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
- payload = "#{Ack::Nak} #{{ delay: params[:delay] }.to_json}"
46
- else
47
- Ack::Nak
48
- end
47
+ "#{Ack::Nak} #{{delay: params[:delay]}.to_json}"
48
+ else
49
+ Ack::Nak
50
+ end
49
51
  resp = if params[:timeout]
50
- @nc.request(@reply, payload, **params)
51
- else
52
- @nc.publish(@reply, payload)
53
- end
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
- @nc.request(@reply, Ack::Term, **params)
64
- else
65
- @nc.publish(@reply, Ack::Term)
66
- end
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
- case
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
- when tokens[0] != Ack::Prefix0 || tokens[1] != Ack::Prefix1
99
+ elsif tokens[0] != Ack::Prefix0 || tokens[1] != Ack::Prefix1
98
100
  raise NotJSMessage.new("nats: not a jetstream message")
99
- when n == Ack::V1TokenCounts
101
+ elsif n == Ack::V1TokenCounts
100
102
  tokens.insert(Ack::Domain, Ack::Empty)
101
103
  tokens.insert(Ack::AccHash, Ack::Empty)
102
- when tokens[Ack::Domain] == Ack::NoDomainName
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 'time'
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 = Ack::SequencePair.new(opts[Ack::StreamSeq].to_i, opts[Ack::ConsumerSeq].to_i)
25
- @domain = opts[Ack::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 = 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]
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 'msg/ack'
16
- require_relative 'msg/ack_methods'
17
- require_relative 'msg/metadata'
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
- end
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 'errors'
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
- msg = nil
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
- if msgs.empty? and duration > timeout
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 and MonotonicTime.since(start_time) < timeout
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? and duration > timeout
217
+ if msgs.empty? && @pending_queue.empty? && (duration > timeout)
214
218
  raise NATS::Timeout.new("nats: fetch timeout")
215
219
  end
216
- else
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