nats-pure 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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 -3
  5. data/lib/nats/io/client.rb +303 -280
  6. data/lib/nats/io/errors.rb +2 -0
  7. data/lib/nats/io/jetstream/api.rb +53 -50
  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 +103 -101
  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 +102 -106
  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,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? 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
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 = case
111
- when config[:name]
112
- ###############################################################################
113
- # #
114
- # Using names is the supported way of creating consumers (NATS +v2.9.0. #
115
- # #
116
- ###############################################################################
117
- if config[:filter_subject] && config[:filter_subject] != ">"
118
- "#{@prefix}.CONSUMER.CREATE.#{stream}.#{config[:name]}.#{config[:filter_subject]}"
119
- else
120
- ##############################################################################
121
- # #
122
- # Endpoint to support creating ANY consumer with multi-filters (NATS +v2.10) #
123
- # #
124
- ##############################################################################
125
- "#{@prefix}.CONSUMER.CREATE.#{stream}.#{config[:name]}"
126
- end
127
- when config[:durable_name]
128
- ###############################################################################
129
- # #
130
- # Endpoint to support creating DURABLES before NATS v2.9.0. #
131
- # #
132
- ###############################################################################
133
- "#{@prefix}.CONSUMER.DURABLE.CREATE.#{stream}.#{config[:durable_name]}"
134
- else
135
- ###############################################################################
136
- # #
137
- # Endpoint to support creating EPHEMERALS before NATS v2.9.0. #
138
- # #
139
- ###############################################################################
140
- "#{@prefix}.CONSUMER.CREATE.#{stream}"
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? or stream.empty?
172
- 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?
173
178
 
174
179
  req_subject = "#{@prefix}.CONSUMER.INFO.#{stream}.#{consumer}"
175
- result = api_request(req_subject, '', params)
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? or stream.empty?
187
- 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?
188
193
 
189
194
  req_subject = "#{@prefix}.CONSUMER.DELETE.#{stream}.#{consumer}"
190
- result = api_request(req_subject, '', params)
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 = { subject: subject }
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
- case
219
- when params[:next]
223
+ if params[:next]
220
224
  req[:seq] = params[:seq]
221
225
  req[:next_by_subj] = params[:subject]
222
- when params[:seq]
226
+ elsif params[:seq]
223
227
  req[:seq] = params[:seq]
224
- when params[:subject]
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] and not params[:seq]
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
- msg = if params[:direct]
242
- _lift_msg_to_raw_msg(resp)
243
- else
244
- JetStream::API::RawStreamMsg.new(resp[:message])
245
- end
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
- @nc.request(req_subject, req, **params)
265
- rescue NATS::IO::NoRespondersError
266
- raise JetStream::Error::ServiceUnavailable
267
- end
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
- msg
271
- else
272
- JSON.parse(msg.data, symbolize_names: true)
273
- end
274
- 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]
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 and msg.header['Status']
283
- status = msg.header['Status']
284
- if status == '404'
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['Nats-Subject']
291
- seq = msg.header['Nats-Sequence']
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 = ("+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