protobuf-nats 0.10.5 → 0.11.0.pre0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2187c7b268795df3d9cb72b75d4bf51456c055bd00253cdc2fc25385cdbb988
4
- data.tar.gz: bd286511daf03a39bf93ad1aa74d8f044b7b1019cb9eb043c40c663e4950f3a2
3
+ metadata.gz: 0fa8475a4054e8c99c04c30193f773ccca511efbf8412a8d26fa162dbb024f4c
4
+ data.tar.gz: 66a92c3b49be6df8f0014a219d9691b847b7432e00d685722739190c30ba9ac5
5
5
  SHA512:
6
- metadata.gz: 2f36143434fadea654a256c365fde72df2932510c8c1430408095d14fd426b512404725c67e621d6b13df9a8aef266fef3a9f4a3945a2d3e6ccb329cc70aa641
7
- data.tar.gz: a79b514f718ea525bde3095de4f5568849f8321c67c703096386bbef74cde0599b4f952ee70b12b6b22b338ea39666faef3d2c6af74585852f3972831adcb36b
6
+ metadata.gz: 0cce76f4edd08e182c665ac53fc5d69e39ccb764855f1335220a197a98b18fa2012c73862071b77b1f0e32a2c8b7d7e60b5c652fe458151733dc3f7f79970c71
7
+ data.tar.gz: a024fd949c96297de7d853bb182503716ed449b1500f217660e8e1bcf4fb2639ca0b12840c002732ef415e9889cea39880b638d2fb3f1859405f750185b4d2d1
data/.travis.yml CHANGED
@@ -1,16 +1,12 @@
1
1
  sudo: false
2
2
  language: ruby
3
- jdk:
4
- - openjdk8
3
+ jdk: openjdk8
5
4
  rvm:
6
5
  - 2.3.0
7
- - 2.7.0
8
6
  - jruby-9.1.7.0
9
- - jruby-9.2.13.0
10
7
  before_install:
11
- # Install and start gnatsd
12
- - ./scripts/install_gnatsd.sh
13
- - $HOME/nats-server/nats-server &
14
- # Install deps for project
15
8
  - gem install bundler
16
9
  - gem update --system
10
+ - wget https://github.com/nats-io/gnatsd/releases/download/v1.3.0/gnatsd-v1.3.0-linux-amd64.zip
11
+ - unzip gnatsd-v1.3.0-linux-amd64.zip
12
+ - ./gnatsd-v1.3.0-linux-amd64/gnatsd &
data/README.md CHANGED
@@ -154,11 +154,9 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
154
154
 
155
155
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
156
156
 
157
- The java-nats client is temporarily forked to support jruby > 9.2.10.0. The living branch for that is here: https://github.com/film42/java-nats/tree/jruby-compat. This will be removed when we upgrade to the new nats.java client.
158
-
159
157
  ## Contributing
160
158
 
161
- Bug reports and pull requests are welcome on GitHub at https://github.com/mxenabled/protobuf-nats.
159
+ Bug reports and pull requests are welcome on GitHub at https://github.com/abrandoned/protobuf-nats.
162
160
 
163
161
 
164
162
  ## License
Binary file
@@ -151,12 +151,12 @@ module Protobuf
151
151
  when :ack_timeout
152
152
  ::ActiveSupport::Notifications.instrument "client.request_timeout.protobuf-nats"
153
153
  next if (retries -= 1) > 0
154
- raise ::Protobuf::Nats::Errors::RequestTimeout, formatted_service_and_method_name
154
+ raise ::Protobuf::Nats::Errors::RequestTimeout
155
155
  when :nack
156
156
  ::ActiveSupport::Notifications.instrument "client.request_nack.protobuf-nats"
157
157
  interval = nack_backoff_intervals[nack_retry]
158
158
  nack_retry += 1
159
- raise ::Protobuf::Nats::Errors::RequestTimeout, formatted_service_and_method_name if interval.nil?
159
+ raise ::Protobuf::Nats::Errors::RequestTimeout if interval.nil?
160
160
  sleep((interval + nack_backoff_splay)/1000.0)
161
161
  next
162
162
  end
@@ -186,12 +186,6 @@ module Protobuf
186
186
  end
187
187
  end
188
188
 
189
- def formatted_service_and_method_name
190
- klass = @options[:service]
191
- method_name = @options[:method]
192
- "#{klass}##{method_name}"
193
- end
194
-
195
189
  # The Java nats client offers better message queueing so we're going to use
196
190
  # that over locking ourselves. This split in code isn't great, but we can
197
191
  # refactor this later.
@@ -213,7 +207,7 @@ module Protobuf
213
207
  begin
214
208
  completed_request = false
215
209
 
216
- if !sub_inbox.subscription.is_valid # replace the subscription if is has been pooled but is no longer valid (maybe a reconnect)
210
+ if !sub_inbox.subscription.is_active # replace the subscription if is has been pooled but is no longer valid (maybe a reconnect)
217
211
  nats.unsubscribe(sub_inbox.subscription)
218
212
  sub_inbox.swap(new_subscription_inbox) # this line replaces the sub_inbox in the connection pool if necessary
219
213
  end
@@ -237,7 +231,7 @@ module Protobuf
237
231
  else return :ack_timeout
238
232
  end
239
233
 
240
- fail(::Protobuf::Nats::Errors::ResponseTimeout, formatted_service_and_method_name) unless response
234
+ fail(::Protobuf::Nats::Errors::ResponseTimeout, subject) unless response
241
235
 
242
236
  completed_request = true
243
237
  response
@@ -293,7 +287,7 @@ module Protobuf
293
287
  else return :ack_timeout
294
288
  end
295
289
 
296
- fail(::Protobuf::Nats::Errors::ResponseTimeout, formatted_service_and_method_name) unless response
290
+ fail(::Protobuf::Nats::Errors::ResponseTimeout, subject) unless response
297
291
 
298
292
  response
299
293
  ensure
@@ -39,13 +39,8 @@ module Protobuf
39
39
  yaml_config = {}
40
40
  config_path = ENV["PROTOBUF_NATS_CONFIG_PATH"] || ::File.join("config", "protobuf_nats.yml")
41
41
  absolute_config_path = ::File.expand_path(config_path)
42
- if ::File.exist?(absolute_config_path)
43
- # Psych 4 and newer requires unsafe_load_file in order for aliases to be used
44
- yaml_config = if ::YAML.respond_to?(:unsafe_load_file)
45
- ::YAML.unsafe_load_file(absolute_config_path)[env]
46
- else
47
- ::YAML.load_file(absolute_config_path)[env]
48
- end
42
+ if ::File.exists?(absolute_config_path)
43
+ yaml_config = ::YAML.load_file(absolute_config_path)[env]
49
44
  end
50
45
 
51
46
  DEFAULTS.each_pair do |key, value|
@@ -1,13 +1,13 @@
1
1
  module Protobuf
2
2
  module Nats
3
3
  module Errors
4
- class ClientError < ::StandardError
4
+ class Base < ::StandardError
5
5
  end
6
6
 
7
- class RequestTimeout < ClientError
7
+ class RequestTimeout < Base
8
8
  end
9
9
 
10
- class ResponseTimeout < ClientError
10
+ class ResponseTimeout < Base
11
11
  end
12
12
 
13
13
  class MriIOException < ::StandardError
@@ -3,12 +3,82 @@ ext_base = ::File.join(::File.dirname(__FILE__), '..', '..', '..', 'ext')
3
3
  require ::File.join(ext_base, "jars/slf4j-api-1.7.25.jar")
4
4
  require ::File.join(ext_base, "jars/slf4j-simple-1.7.25.jar")
5
5
  require ::File.join(ext_base, "jars/gson-2.6.2.jar")
6
- require ::File.join(ext_base, "jars/jnats-1.1-SNAPSHOT.jar")
6
+ require ::File.join(ext_base, "jars/jnats-2.6.0.jar")
7
7
 
8
8
  module Protobuf
9
9
  module Nats
10
10
  class JNats
11
- attr_reader :connection, :options
11
+ attr_reader :connection, :dispatcher, :options
12
+
13
+ class MessageHandlerProxy
14
+ include ::Java::IoNatsClient::MessageHandler
15
+
16
+ def self.empty
17
+ new {}
18
+ end
19
+
20
+ def initialize(&block)
21
+ @cb = block
22
+ end
23
+
24
+ def onMessage(message)
25
+ @cb.call(message.getData.to_s, message.getReplyTo, message.getSubject)
26
+ end
27
+ end
28
+
29
+ class ConnectionListener
30
+ include ::Java::IoNatsClient::ConnectionListener
31
+
32
+ def initialize
33
+ @on_reconnect_cb = lambda {}
34
+ @on_disconnect_cb = lambda {}
35
+ @on_close_cb = lambda {}
36
+ end
37
+
38
+ def on_close(&block); @on_close_cb = block; end
39
+ def on_disconnect(&block); @on_disconnect_cb = block; end
40
+ def on_reconnect(&block); @on_reconnect_cb = block; end
41
+
42
+ def connectionEvent(conn, event_type)
43
+ case event_type
44
+ when ::Java::IoNatsClient::ConnectionListener::Events::RECONNECTED
45
+ @on_reconnect_cb.call
46
+ when ::Java::IoNatsClient::ConnectionListener::Events::DISCONNECTED
47
+ @on_disconnect_cb.call
48
+ when ::Java::IoNatsClient::ConnectionListener::Events::CLOSED
49
+ @on_close_cb.call
50
+ end
51
+ end
52
+ end
53
+
54
+ class ErrorListener
55
+ include ::Java::IoNatsClient::ErrorListener
56
+
57
+ def initialize
58
+ @on_error_cb = lambda { |_error| }
59
+ @on_exception_cb = lambda { |_exception| }
60
+ @on_slow_consumer_cb = lambda { |_consumer| }
61
+ end
62
+
63
+ def on_error(&block)
64
+ return if block.nil? || block.arity != 1
65
+ @on_error_cb = block
66
+ end
67
+
68
+ def on_exception(&block)
69
+ return if block.nil? || block.arity != 1
70
+ @on_exception_cb = block
71
+ end
72
+
73
+ def on_slow_consumer(&block)
74
+ return if block.nil? || block.arity != 1
75
+ @on_slow_consumer_cb = block
76
+ end
77
+
78
+ def errorOccurred(_conn, error); @on_error_cb.call(error); end
79
+ def exceptionOccurred(_conn, exception); @on_exception_cb.call(exception); end
80
+ def slowConsumerDetected(_conn, consumer); @on_slow_consumer_cb.call(consumer); end
81
+ end
12
82
 
13
83
  class Message
14
84
  attr_reader :data, :subject, :reply
@@ -21,10 +91,9 @@ module Protobuf
21
91
  end
22
92
 
23
93
  def initialize
24
- @on_error_cb = lambda {|error|}
25
- @on_reconnect_cb = lambda {}
26
- @on_disconnect_cb = lambda {}
27
- @on_close_cb = lambda {}
94
+ @connection_listener = ConnectionListener.new
95
+ @error_listener = ErrorListener.new
96
+
28
97
  @options = nil
29
98
  @subz_cbs = {}
30
99
  @subz_mutex = ::Mutex.new
@@ -34,35 +103,26 @@ module Protobuf
34
103
  @options ||= options
35
104
 
36
105
  servers = options[:servers] || ["nats://localhost:4222"]
37
- servers = [servers].flatten.map { |uri_string| java.net.URI.new(uri_string) }
38
- connection_factory = ::Java::IoNatsClient::ConnectionFactory.new
39
- connection_factory.setServers(servers)
40
- connection_factory.setMaxReconnect(options[:max_reconnect_attempts])
106
+ servers = [servers].flatten
107
+
108
+ builder = ::Java::IoNatsClient::Options::Builder.new
109
+ builder.servers(servers)
110
+ builder.maxReconnects(options[:max_reconnect_attempts])
111
+ builder.errorListener(@error_listener)
41
112
 
42
113
  # Shrink the pending buffer to always raise an error and let the caller retry.
43
114
  if options[:disable_reconnect_buffer]
44
- connection_factory.setReconnectBufSize(1)
115
+ builder.reconnectBufferSize(1)
45
116
  end
46
117
 
47
- # Setup callbacks
48
- connection_factory.setDisconnectedCallback { |event| @on_disconnect_cb.call }
49
- connection_factory.setReconnectedCallback { |_event| @on_reconnect_cb.call }
50
- connection_factory.setClosedCallback { |_event| @on_close_cb.call }
51
- connection_factory.setExceptionHandler { |error| @on_error_cb.call(error) }
52
-
53
118
  # Setup ssl context if we're using tls
54
119
  if options[:uses_tls]
55
120
  ssl_context = create_ssl_context(options)
56
- connection_factory.setSecure(true)
57
- connection_factory.setSSLContext(ssl_context)
121
+ builder.sslContext(ssl_context)
58
122
  end
59
123
 
60
- @connection = connection_factory.createConnection
61
-
62
- # We're going to spawn a consumer and supervisor
63
- @work_queue = @connection.createMsgChannel
64
- spwan_supervisor_and_consumer
65
-
124
+ @connection = ::Java::IoNatsClient::Nats.connect(builder.build)
125
+ @dispatcher = @connection.createDispatcher(MessageHandlerProxy.empty)
66
126
  @connection
67
127
  end
68
128
 
@@ -75,64 +135,56 @@ module Protobuf
75
135
 
76
136
  # Do not depend on #close for a graceful disconnect.
77
137
  def close
78
- @connection.close rescue nil
138
+ if @connection
139
+ @connection.closeDispatcher(@dispatcher) rescue nil
140
+ @connection.close rescue nil
141
+ end
142
+ @dispatcher = nil
79
143
  @connection = nil
80
- @supervisor.kill rescue nil
81
- @supervisor = nil
82
- @consumer.kill rescue nil
83
- @supervisor = nil
84
144
  end
85
145
 
86
146
  def flush(timeout_sec = 0.5)
87
- connection.flush(timeout_sec * 1000)
147
+ duration = duration_in_ms(timeout_sec * 1000)
148
+ connection.flush(duration)
88
149
  end
89
150
 
90
151
  def next_message(sub, timeout_sec)
91
- nats_message = sub.nextMessage(timeout_sec * 1000)
152
+ duration = duration_in_ms(timeout_sec * 1000)
153
+ nats_message = sub.nextMessage(duration)
92
154
  return nil unless nats_message
93
155
  Message.new(nats_message)
94
156
  end
95
157
 
96
158
  def publish(subject, data, mailbox = nil)
97
159
  # The "true" here is to force flush. May not need this.
98
- connection.publish(subject, mailbox, data.to_java_bytes, true)
160
+ connection.publish(subject, mailbox, data.to_java_bytes)
161
+ connection.flush(nil)
99
162
  end
100
163
 
101
164
  def subscribe(subject, options = {}, &block)
102
165
  queue = options[:queue]
103
166
  max = options[:max]
104
- work_queue = nil
105
- # We pass our work queue for processing async work because java nats
106
- # uses a cahced thread pool: 1 thread per async subscription.
107
- # Sync subs need their own queue so work is not processed async.
108
- work_queue = block.nil? ? connection.createMsgChannel : @work_queue
109
- sub = connection.subscribe(subject, queue, nil, work_queue)
110
-
111
- # Register the block callback. We only lock to save the callback.
167
+
112
168
  if block
113
- @subz_mutex.synchronize do
114
- @subz_cbs[sub.getSid] = block
115
- end
169
+ handler = MessageHandlerProxy.new(&block)
170
+ sub = subscribe_using_subscription_dispatcher(subject, queue, handler)
171
+ # Auto unsub if max message option was provided.
172
+ dispatcher.unsubscribe(sub, max) if max
173
+ sub
174
+ else
175
+ sub = subscribe_using_connection(subject, queue)
176
+ sub.unsubscribe(max) if max
177
+ sub
116
178
  end
117
-
118
- # Auto unsub if max message option was provided.
119
- sub.autoUnsubscribe(max) if max
120
-
121
- sub
122
179
  end
123
180
 
124
181
  def unsubscribe(sub)
125
182
  return if sub.nil?
126
-
127
- # Cleanup our async callback
128
- if @subz_cbs[sub.getSid]
129
- @subz_mutex.synchronize do
130
- @subz_cbs.delete(sub.getSid)
131
- end
183
+ if sub.getDispatcher
184
+ dispatcher.unsubscribe(sub)
185
+ else
186
+ sub.unsubscribe()
132
187
  end
133
-
134
- # The "true" here is to ignore and invalid conn.
135
- sub.unsubscribe(true)
136
188
  end
137
189
 
138
190
  def new_inbox
@@ -140,69 +192,23 @@ module Protobuf
140
192
  end
141
193
 
142
194
  def on_reconnect(&cb)
143
- @on_reconnect_cb = cb
195
+ @connection_listener.on_reconnect(&cb)
144
196
  end
145
197
 
146
198
  def on_disconnect(&cb)
147
- @on_disconnect_cb = cb
199
+ @connection_listener.on_disconnect(&cb)
148
200
  end
149
201
 
150
202
  def on_error(&cb)
151
- @on_error_cb = cb
203
+ @error_listener.on_exception(&cb)
152
204
  end
153
205
 
154
206
  def on_close(&cb)
155
- @on_close_cb = cb
207
+ @connection_listener.on_close(&cb)
156
208
  end
157
209
 
158
210
  private
159
211
 
160
- def spwan_supervisor_and_consumer
161
- spawn_consumer
162
- @supervisor = ::Thread.new do
163
- loop do
164
- begin
165
- sleep 1
166
- next if @consumer && @consumer.alive?
167
- # We need to recreate the consumer thread
168
- @consumer.kill if @consumer
169
- spawn_consumer
170
- rescue => error
171
- @on_error_cb.call(error)
172
- end
173
- end
174
- end
175
- end
176
-
177
- def spawn_consumer
178
- @consumer = ::Thread.new do
179
- loop do
180
- begin
181
- message = @work_queue.take
182
- next unless message
183
- sub = message.getSubscription
184
-
185
- # We have to update the subscription stats so we're not considered a slow consumer.
186
- begin
187
- sub.lock
188
- sub.incrPMsgs(-1)
189
- sub.incrPBytes(-message.getData.length) if message.getData
190
- sub.incrDelivered(1) unless sub.isClosed
191
- ensure
192
- sub.unlock
193
- end
194
-
195
- # We don't need t
196
- callback = @subz_cbs[sub.getSid]
197
- next unless callback
198
- callback.call(message.getData.to_s, message.getReplyTo, message.getSubject)
199
- rescue => error
200
- @on_error_cb.call(error)
201
- end
202
- end
203
- end
204
- end
205
-
206
212
  # Jruby-openssl depends on bouncycastle so our lives don't suck super bad
207
213
  def read_pem_object_from_file(path)
208
214
  fail ::ArgumentError, "Tried to read a PEM key or cert with path nil" if path.nil?
@@ -246,6 +252,30 @@ module Protobuf
246
252
  context.init(key_manager.getKeyManagers, trust_manager.getTrustManagers, nil)
247
253
  context
248
254
  end
255
+
256
+ def duration_in_ms(ms)
257
+ ::Java::JavaTime::Duration.ofMillis(ms)
258
+ end
259
+
260
+ def subscribe_using_connection(subject, queue)
261
+ if queue
262
+ connection.subscribe(subject, queue)
263
+ else
264
+ connection.subscribe(subject)
265
+ end
266
+ end
267
+
268
+ def subscribe_using_subscription_dispatcher(subject, queue, handler)
269
+ if queue
270
+ dispatcher.java_send(:subscribe,
271
+ [::Java::JavaLang::String, ::Java::JavaLang::String, ::Java::IoNatsClient::MessageHandler],
272
+ subject, queue, handler)
273
+ else
274
+ dispatcher.java_send(:subscribe,
275
+ [::Java::JavaLang::String, ::Java::IoNatsClient::MessageHandler],
276
+ subject, handler)
277
+ end
278
+ end
249
279
  end
250
280
  end
251
281
  end
@@ -1,5 +1,5 @@
1
1
  module Protobuf
2
2
  module Nats
3
- VERSION = "0.10.5"
3
+ VERSION = "0.11.0.pre0"
4
4
  end
5
5
  end
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = %q{ ruby-protobuf client/server for nats }
13
13
  spec.description = %q{ ruby-protobuf client/server for nats }
14
- spec.homepage = "https://github.com/mxenabled/protobuf-nats"
14
+ #spec.homepage = "TODO: Put your gem's website or public repo URL here."
15
15
  spec.license = "MIT"
16
16
 
17
17
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protobuf-nats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.5
4
+ version: 0.11.0.pre0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Dewitt
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-01 00:00:00.000000000 Z
11
+ date: 2019-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -171,7 +171,7 @@ files:
171
171
  - examples/warehouse/start_client.sh
172
172
  - examples/warehouse/start_server.sh
173
173
  - ext/jars/gson-2.6.2.jar
174
- - ext/jars/jnats-1.1-SNAPSHOT.jar
174
+ - ext/jars/jnats-2.6.0.jar
175
175
  - ext/jars/slf4j-api-1.7.25.jar
176
176
  - ext/jars/slf4j-simple-1.7.25.jar
177
177
  - lib/protobuf/nats.rb
@@ -184,13 +184,12 @@ files:
184
184
  - lib/protobuf/nats/thread_pool.rb
185
185
  - lib/protobuf/nats/version.rb
186
186
  - protobuf-nats.gemspec
187
- - scripts/install_gnatsd.sh
188
- homepage: https://github.com/mxenabled/protobuf-nats
187
+ homepage:
189
188
  licenses:
190
189
  - MIT
191
190
  metadata:
192
191
  allowed_push_host: https://rubygems.org
193
- post_install_message:
192
+ post_install_message:
194
193
  rdoc_options: []
195
194
  require_paths:
196
195
  - lib
@@ -201,12 +200,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
201
200
  version: '0'
202
201
  required_rubygems_version: !ruby/object:Gem::Requirement
203
202
  requirements:
204
- - - ">="
203
+ - - ">"
205
204
  - !ruby/object:Gem::Version
206
- version: '0'
205
+ version: 1.3.1
207
206
  requirements: []
208
- rubygems_version: 3.4.20
209
- signing_key:
207
+ rubyforge_project:
208
+ rubygems_version: 2.7.6
209
+ signing_key:
210
210
  specification_version: 4
211
211
  summary: ruby-protobuf client/server for nats
212
212
  test_files: []
Binary file
@@ -1,20 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -e
4
-
5
- export DEFAULT_NATS_SERVER_VERSION=v2.0.0
6
-
7
- export NATS_SERVER_VERSION="${NATS_SERVER_VERSION:=$DEFAULT_NATS_SERVER_VERSION}"
8
-
9
- # check to see if nats-server folder is empty
10
- if [ ! "$(ls -A $HOME/nats-server)" ]; then
11
- (
12
- mkdir -p $HOME/nats-server
13
- cd $HOME/nats-server
14
- wget https://github.com/nats-io/nats-server/releases/download/$NATS_SERVER_VERSION/nats-server-$NATS_SERVER_VERSION-linux-amd64.zip -O nats-server.zip
15
- unzip nats-server.zip
16
- cp nats-server-$NATS_SERVER_VERSION-linux-amd64/nats-server $HOME/nats-server/nats-server
17
- )
18
- else
19
- echo 'Using cached directory.';
20
- fi