zoomq 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/lib/zoomq/cli.rb +1 -1
- data/lib/zoomq/client/connection.rb +18 -0
- data/lib/zoomq/client.rb +32 -20
- data/lib/zoomq/console.rb +34 -0
- data/lib/zoomq/server/{request_handler.rb → connection.rb} +10 -11
- data/lib/zoomq/server/worker.rb +14 -16
- data/lib/zoomq/server.rb +14 -11
- data/lib/zoomq/socket.rb +43 -0
- data/lib/zoomq/zookeeper.rb +2 -2
- data/templates/client.rb.tt +4 -10
- data/templates/console.rb.tt +4 -23
- data/templates/ping_request.rb.tt +5 -3
- data/templates/protocol.proto.tt +1 -1
- data/templates/server.rb.tt +2 -12
- data/zoomq.gemspec +2 -1
- metadata +22 -5
- data/lib/zoomq/handler.rb +0 -13
- data/lib/zoomq/jeromq-0.3.0-20130721.175323-20.jar +0 -0
data/Gemfile
CHANGED
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}/
|
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 '
|
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
|
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
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@
|
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
|
-
|
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
|
44
|
+
def request(obj)
|
41
45
|
if @servers.empty?
|
42
|
-
raise
|
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
|
-
|
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
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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 '
|
3
|
+
require 'zmachine/connection'
|
4
4
|
|
5
5
|
module ZooMQ
|
6
6
|
class Server
|
7
|
-
class
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
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))
|
data/lib/zoomq/server/worker.rb
CHANGED
@@ -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 '
|
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
|
21
|
-
|
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
|
29
|
-
|
30
|
-
|
31
|
-
|
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 :
|
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
|
-
@
|
23
|
-
@zk = Zookeeper.new(
|
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
|
data/lib/zoomq/socket.rb
ADDED
@@ -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
|
data/lib/zoomq/zookeeper.rb
CHANGED
@@ -7,8 +7,8 @@ module ZooMQ
|
|
7
7
|
attr_reader :globals
|
8
8
|
attr_reader :locals
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@zk = ZK.new(
|
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
|
data/templates/client.rb.tt
CHANGED
@@ -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
|
-
|
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
|
21
|
-
@client.handle(request)
|
15
|
+
request(PingRequest.new)
|
22
16
|
end
|
23
17
|
|
24
18
|
end
|
data/templates/console.rb.tt
CHANGED
@@ -1,29 +1,10 @@
|
|
1
|
-
require '
|
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
|
-
|
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
|
data/templates/protocol.proto.tt
CHANGED
data/templates/server.rb.tt
CHANGED
@@ -9,18 +9,8 @@ end
|
|
9
9
|
module <%=config[:constant_name]%>
|
10
10
|
class Server
|
11
11
|
|
12
|
-
def
|
13
|
-
|
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.
|
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.
|
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-
|
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/
|
127
|
-
- lib/zoomq/
|
142
|
+
- lib/zoomq/client/connection.rb
|
143
|
+
- lib/zoomq/console.rb
|
128
144
|
- lib/zoomq/server.rb
|
129
|
-
- lib/zoomq/server/
|
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
Binary file
|