zoomq 0.1.1 → 0.2.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.
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem 'zmachine', path: '../zmachine'
data/lib/zoomq/cli.rb CHANGED
@@ -73,7 +73,7 @@ module ZooMQ
73
73
  "lib/#{name}/client.rb" => "client.rb",
74
74
  "lib/#{name}/console.rb" => "console.rb",
75
75
  "#{name}/server.rb" => "server.rb",
76
- "#{name}/server/ping_request.rb" => "ping_request.rb",
76
+ "#{name}/protocol/ping_request.rb" => "ping_request.rb",
77
77
  }.each do |dest, source|
78
78
  puts " * #{dest}"
79
79
  source = File.join(@root, 'templates', "#{source}.tt")
@@ -0,0 +1,18 @@
1
+ module ZooMQ
2
+ class Client
3
+ class Connection < ZMachine::Connection
4
+
5
+ attr_accessor :client
6
+
7
+ def receive_data(msg)
8
+ msg.unwrap # strip origin
9
+ # TODO: unwrap data to string from bytes to_i wtf
10
+ request_id = String.from_java_bytes(msg.unwrap.data).to_i
11
+ cls = String.from_java_bytes(msg.pop.data).constantize
12
+ obj = cls.parse(String.from_java_bytes(msg.pop.data))
13
+ @client.response(request_id, obj)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
data/lib/zoomq/client.rb CHANGED
@@ -1,25 +1,28 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'zoomq/jeromq-0.3.0-20130721.175323-20.jar'
4
- java_import org.zeromq.ZMQ
5
- java_import org.zeromq.ZContext
6
- java_import org.zeromq.ZMsg
7
- java_import org.zeromq.ZFrame
3
+ require 'zmachine'
8
4
 
9
5
  require 'zoomq/zookeeper'
6
+ require 'zoomq/client/connection'
7
+
8
+ java_import org.zeromq.ZFrame
9
+ java_import java.util.concurrent.atomic.AtomicInteger
10
10
 
11
11
  module ZooMQ
12
- class ServerUnavailable < StandardError; end
12
+ class ServerUnavailableError < StandardError; end
13
+ class TimeoutError < StandardError; end
13
14
 
14
15
  class Client
15
16
 
16
17
  attr_reader :servers
17
18
 
18
- def initialize(service_name, zookeeper_uri, log)
19
- @zk = Zookeeper.new("#{zookeeper_uri}/#{service_name}")
20
- @ctx = ZContext.new
21
- @socket = @ctx.create_socket(ZMQ::ROUTER)
22
- @socket.identity = SecureRandom.uuid.to_java_bytes
19
+ def initialize
20
+ @requests = {}
21
+ @request_id = AtomicInteger.new
22
+ @zk = Zookeeper.new(service_name)
23
+ @channel = ZMachine.connect(nil, ZMQ::ROUTER, Connection) do |connection|
24
+ connection.client = self
25
+ end
23
26
  watch
24
27
  refresh
25
28
  end
@@ -31,27 +34,36 @@ module ZooMQ
31
34
  def refresh
32
35
  @servers = @zk.servers
33
36
  @servers.each do |server|
34
- @socket.connect("tcp://#{server}")
37
+ $log.debug("#{service_name}:connect", server: server)
38
+ @channel.connect("tcp://#{server}")
35
39
  sleep(0.1)
36
40
  end
37
41
  @cycle = @servers.cycle
38
42
  end
39
43
 
40
- def handle(request)
44
+ def request(obj)
41
45
  if @servers.empty?
42
- raise ServerUnavailable.new("no servers are online, please try again later")
46
+ raise ServerUnavailableError.new("no servers are online, please try again later")
43
47
  end
44
48
 
45
49
  server = @cycle.next
46
50
 
47
- msg = ZMsg.new_string_msg(request.class.to_s, request.to_s)
51
+ deferred = ZMachine::DefaultDeferrable.new
52
+ deferred.callback { |result| yield result } if block_given?
53
+
54
+ request_id = @request_id.increment_and_get
55
+ msg = ZMsg.new_string_msg(obj.class.to_s, obj.to_s)
56
+ msg.wrap(ZFrame.new(request_id.to_s))
48
57
  msg.wrap(ZFrame.new(server))
49
- msg.send(@socket)
58
+ $log.debug("#{service_name}:request", id: request_id, obj: obj.inspect)
59
+ @channel.send_data(msg)
60
+
61
+ @requests[request_id] = deferred
62
+ end
50
63
 
51
- msg = ZMsg.recvMsg(@socket)
52
- msg.unwrap
53
- cls = String.from_java_bytes(msg.pop.data).constantize
54
- cls.parse(String.from_java_bytes(msg.pop.data))
64
+ def response(request_id, obj)
65
+ $log.debug("#{service_name}:response", id: request_id, obj: obj.inspect)
66
+ @requests[request_id].succeed(obj)
55
67
  end
56
68
 
57
69
  end
@@ -0,0 +1,34 @@
1
+ require 'ap'
2
+ require 'irb'
3
+ require 'ripl'
4
+
5
+ Ripl::Shell.class_eval do
6
+ def format_result(result)
7
+ ap(result)
8
+ end
9
+ end
10
+
11
+ module ZooMQ
12
+ class Console
13
+ def initialize
14
+ $log.level = :info
15
+ Thread.new { zmachine }
16
+ Ripl.start(binding: binding)
17
+ end
18
+
19
+ def zmachine
20
+ ZMachine.run { client }
21
+ end
22
+
23
+ def method_missing(name, *args, &block)
24
+ result = nil
25
+ df = @client.send(name, *args, &block)
26
+ df.callback { |response| result = response }
27
+ df.errback { |error| result = error }
28
+ while result.nil?
29
+ sleep(0.1)
30
+ end
31
+ result
32
+ end
33
+ end
34
+ end
@@ -1,24 +1,23 @@
1
1
  java_import org.zeromq.ZMsg
2
2
 
3
- require 'zoomq/handler'
3
+ require 'zmachine/connection'
4
4
 
5
5
  module ZooMQ
6
6
  class Server
7
- class RequestHandler < Handler
8
- def handle(zloop, poller, worker)
9
- @server = worker.server
10
- origin, msg = recv_msg(poller.socket)
7
+ class Connection < ZMachine::Connection
8
+
9
+ attr_accessor :server
10
+
11
+ def receive_data(msg)
12
+ origin = msg.unwrap
13
+ request_id = msg.unwrap
11
14
  result = handle_msg(msg)
15
+ result.wrap(request_id)
12
16
  result.wrap(origin)
13
- result.send(poller.socket)
17
+ send_data(result)
14
18
  return 0
15
19
  end
16
20
 
17
- def recv_msg(socket)
18
- msg = ZMsg.recvMsg(socket)
19
- [msg.unwrap, msg]
20
- end
21
-
22
21
  def handle_msg(msg)
23
22
  cls = String.from_java_bytes(msg.pop.data).constantize
24
23
  request = cls.parse(String.from_java_bytes(msg.pop.data))
@@ -1,8 +1,7 @@
1
1
  java_import org.zeromq.ZMQ
2
- java_import org.zeromq.ZContext
3
- java_import org.zeromq.ZLoop
4
2
 
5
- require 'zoomq/server/request_handler'
3
+ require 'zmachine'
4
+ require 'zoomq/server/connection'
6
5
 
7
6
  module ZooMQ
8
7
  class Server
@@ -12,23 +11,22 @@ module ZooMQ
12
11
 
13
12
  def initialize(server)
14
13
  @server = server
15
- @zloop = ZLoop.new
16
- @zloop.verbose(true)
17
- initialize_socket
18
14
  end
19
15
 
20
- def initialize_socket
21
- @socket = @server.create_socket(ZMQ::ROUTER)
22
- @port = @socket.bind("tcp://*:*")
23
- RequestHandler.new(@socket).register(@zloop, self)
24
- Thread.current.name = "#{@server.fqdn}:#{@port}"
25
- @socket.identity = Thread.current[:name].to_java_bytes
16
+ def run
17
+ ZMachine.run { initialize_socket }
26
18
  end
27
19
 
28
- def run
29
- @server.log.info("pubdater:worker", run: true, announce: @socket.identity)
30
- @server.announce(@socket.identity)
31
- @zloop.start
20
+ def initialize_socket
21
+ $log.info("zoomq:server:worker", bind: "tcp://*:*")
22
+ ZMachine.start_server("tcp://*:*", ZMQ::ROUTER, Connection) do |handler|
23
+ identity = "#{@server.fqdn}:#{handler.channel.port}"
24
+ $log.info("zoomq:server:worker", announce: identity)
25
+ Thread.current.name = "ZMQ::Server::Worker (#{identity})"
26
+ handler.channel.identity = identity
27
+ handler.server = @server
28
+ @server.announce(identity)
29
+ end
32
30
  end
33
31
 
34
32
  end
data/lib/zoomq/server.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'zoomq/jeromq-0.3.0-20130721.175323-20.jar'
4
- java_import org.zeromq.ZMQ
5
-
6
3
  require 'forwardable'
4
+ require 'socket'
5
+ require 'zmachine'
7
6
 
8
7
  require 'zoomq/zookeeper'
9
8
  require 'zoomq/server/worker'
@@ -13,25 +12,29 @@ module ZooMQ
13
12
 
14
13
  extend Forwardable
15
14
  def_delegators :@zk, :globals, :locals, :announce
16
- def_delegators :@ctx, :create_socket
17
15
 
18
- attr_reader :log, :fqdn, :port
16
+ attr_reader :fqdn, :port
17
+
18
+ def initialize
19
+ $log.info("#{service_name}:initialize #{RUBY_DESCRIPTION}")
20
+ $log.info("#{service_name}:initialize", {
21
+ env: Env.mode,
22
+ })
19
23
 
20
- def initialize(service_name, zookeeper_uri, log)
21
24
  Signal.register_shutdown_handler { shutdown }
22
- @log = log
23
- @zk = Zookeeper.new("#{zookeeper_uri}/#{service_name}")
24
- @ctx = ZContext.new
25
- @fqdn = Socket.gethostbyname(Socket.gethostname).first
25
+ @fqdn = ::Socket.gethostbyname(::Socket.gethostname).first
26
+ @zk = Zookeeper.new(service_name)
26
27
  end
27
28
 
28
29
  def run
30
+ # TODO: make it multi-threaded
31
+ $log.info("#{service_name}:run", workers: 1)
29
32
  Worker.new(self).run
30
33
  end
31
34
 
32
35
  def shutdown
33
- @ctx.destroy if @ctx
34
36
  @zk.close if @zk
37
+ ZMachine.stop_event_loop
35
38
  end
36
39
 
37
40
  end
@@ -0,0 +1,43 @@
1
+ java_import org.zeromq.ZMQ
2
+
3
+ require 'zmachine/connection'
4
+
5
+ module ZooMQ
6
+ class Socket < ZMachine::Connection
7
+ READABLES = [ ZMQ::SUB, ZMQ::PULL, ZMQ::ROUTER, ZMQ::DEALER, ZMQ::REP, ZMQ::REQ, ZMQ::PAIR ]
8
+ WRITABLES = [ ZMQ::PUB, ZMQ::PUSH, ZMQ::ROUTER, ZMQ::DEALER, ZMQ::REP, ZMQ::REQ, ZMQ::PAIR ]
9
+
10
+ def initialize(socket, socket_type, server)
11
+ @socket, @socket_type, @server = socket, socket_type, server
12
+ self.notify_readable = true if READABLES.include?(socket_type)
13
+ #self.notify_writable = true if WRITABLES.include?(socket_type)
14
+ end
15
+
16
+ def notify_readable
17
+ # Not sure if this is actually necessary. I suppose it prevents us
18
+ # from having to to instantiate a ZMQ::Message unnecessarily.
19
+ # I'm leaving this in because its in the docs, but it could probably
20
+ # be taken out.
21
+ return unless readable?
22
+ handle_readable
23
+ end
24
+
25
+ #def notify_writable
26
+ # return unless writable?
27
+
28
+ # # once a writable event is successfully received the socket
29
+ # # should be accepting messages again so stop triggering
30
+ # # write events
31
+ # self.notify_writable = false
32
+ # handle_writable
33
+ #end
34
+
35
+ def readable?
36
+ (@socket.events & ZMQ::Poller::POLLIN) == ZMQ::Poller::POLLIN
37
+ end
38
+
39
+ def writable?
40
+ (@socket.events & ZMQ::Poller::POLLOUT) == ZMQ::Poller::POLLOUT
41
+ end
42
+ end
43
+ end
@@ -7,8 +7,8 @@ module ZooMQ
7
7
  attr_reader :globals
8
8
  attr_reader :locals
9
9
 
10
- def initialize(uri)
11
- @zk = ZK.new(uri)
10
+ def initialize(service_name)
11
+ @zk = ZK.new("#{$conf.zookeeper}/#{service_name}")
12
12
  @zk.mkdir_p("/alive")
13
13
  @globals = KeySpace.new(:global, @zk)
14
14
  end
@@ -1,24 +1,18 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'forwardable'
4
3
  require 'zoomq/client'
5
4
 
6
5
  require '<%=config[:name]%>/protocol'
7
6
 
8
7
  module <%=config[:constant_name]%>
9
- class Client
8
+ class Client < ZooMQ::Client
10
9
 
11
- extend Forwardable
12
-
13
- def initialize(zookeeper, log)
14
- @client = ZooMQ::Client.new(<%=config[:name].inspect%>, zookeeper, log)
10
+ def service_name
11
+ <%=config[:name].inspect%>
15
12
  end
16
13
 
17
- def_delegators :@client, :servers
18
-
19
14
  def ping
20
- request = PingRequest.new
21
- @client.handle(request)
15
+ request(PingRequest.new)
22
16
  end
23
17
 
24
18
  end
@@ -1,29 +1,10 @@
1
- require 'ap'
2
- require 'irb'
3
- require 'ripl'
4
- require 'forwardable'
5
-
1
+ require 'zoomq/console'
6
2
  require '<%=config[:name]%>/client'
7
3
 
8
- Ripl::Shell.class_eval do
9
- def format_result(result)
10
- ap(result)
11
- end
12
- end
13
-
14
4
  module <%=config[:constant_name]%>
15
- class Console
16
-
17
- extend Forwardable
18
- def initialize
19
- $log.level = :info
20
- @client = Client.new($conf.zookeeper, $log)
21
- Ripl.start(binding: binding)
22
- end
23
-
24
- def method_missing(name, *args, &block)
25
- @client.__send__(name, *args, &block)
5
+ class Console < ZooMQ::Console
6
+ def client
7
+ @client = Client.new
26
8
  end
27
-
28
9
  end
29
10
  end
@@ -1,9 +1,11 @@
1
1
  require '<%=config[:name]%>/protocol'
2
2
 
3
3
  module <%=config[:constant_name]%>
4
- class PingRequest
5
- def handle(server)
6
- PingResponse.new
4
+ module Protocol
5
+ class PingRequest
6
+ def handle(server)
7
+ PingResponse.new
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -1,4 +1,4 @@
1
- package <%=config[:name]%>;
1
+ package <%=config[:name]%>.protocol;
2
2
 
3
3
  message PingRequest {
4
4
  }
@@ -9,18 +9,8 @@ end
9
9
  module <%=config[:constant_name]%>
10
10
  class Server
11
11
 
12
- def initialize
13
- $log.info("<%=config[:name]%>:initialize #{RUBY_DESCRIPTION}")
14
- $log.info("<%=config[:name]%>:initialize", {
15
- env: Env.mode,
16
- })
17
-
18
- @server = ZooMQ::Server.new(<%=config[:name].inspect%>, $conf.zookeeper, $log)
19
- end
20
-
21
- def run
22
- $log.info("<%=config[:name]%>:run")
23
- @server.run
12
+ def service_name
13
+ <%=config[:name].inspect%>
24
14
  end
25
15
 
26
16
  end
data/zoomq.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "zoomq"
5
- spec.version = "0.1.1"
5
+ spec.version = "0.2.0"
6
6
  spec.authors = ["madvertise Mobile Advertising GmbH"]
7
7
  spec.email = ["tech@madvertise.com"]
8
8
  spec.description = %q{ØMQ ROUTER/ROUTER coordinated by Zookeeper}
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "multi_json"
22
22
  spec.add_dependency "ruby-protocol-buffers"
23
23
  spec.add_dependency "zk"
24
+ spec.add_dependency "zmachine"
24
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zoomq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-06 00:00:00.000000000 Z
12
+ date: 2013-08-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: erubis
@@ -107,6 +107,22 @@ dependencies:
107
107
  none: false
108
108
  prerelease: false
109
109
  type: :runtime
110
+ - !ruby/object:Gem::Dependency
111
+ name: zmachine
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ none: false
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ none: false
124
+ prerelease: false
125
+ type: :runtime
110
126
  description: ØMQ ROUTER/ROUTER coordinated by Zookeeper
111
127
  email:
112
128
  - tech@madvertise.com
@@ -123,11 +139,12 @@ files:
123
139
  - bin/zoomq
124
140
  - lib/zoomq/cli.rb
125
141
  - lib/zoomq/client.rb
126
- - lib/zoomq/handler.rb
127
- - lib/zoomq/jeromq-0.3.0-20130721.175323-20.jar
142
+ - lib/zoomq/client/connection.rb
143
+ - lib/zoomq/console.rb
128
144
  - lib/zoomq/server.rb
129
- - lib/zoomq/server/request_handler.rb
145
+ - lib/zoomq/server/connection.rb
130
146
  - lib/zoomq/server/worker.rb
147
+ - lib/zoomq/socket.rb
131
148
  - lib/zoomq/zookeeper.rb
132
149
  - templates/Gemfile.tt
133
150
  - templates/LICENSE.txt.tt
data/lib/zoomq/handler.rb DELETED
@@ -1,13 +0,0 @@
1
- java_import org.zeromq.ZMQ
2
-
3
- module ZooMQ
4
- class Handler
5
- def initialize(socket, flags=ZMQ::Poller::POLLIN)
6
- @poller = ZMQ::PollItem.new(socket, flags)
7
- end
8
-
9
- def register(zloop, opts)
10
- zloop.add_poller(@poller, self, opts)
11
- end
12
- end
13
- end