arpie 0.0.1
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/COPYING +15 -0
- data/README +89 -0
- data/Rakefile +111 -0
- data/lib/arpie.rb +4 -0
- data/lib/arpie/endpoint.rb +94 -0
- data/lib/arpie/protocol.rb +51 -0
- data/lib/arpie/proxy.rb +46 -0
- data/lib/arpie/transport.rb +37 -0
- data/spec/rcov.opts +0 -0
- data/spec/spec.opts +0 -0
- data/tools/benchmark.rb +57 -0
- metadata +73 -0
data/COPYING
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Copyright (C) 2008 Bernhard Stoeckner <elven@swordcoast.net> and contributors
|
2
|
+
|
3
|
+
This program is free software; you can redistribute it and/or modify
|
4
|
+
it under the terms of the GNU General Public License as published by
|
5
|
+
the Free Software Foundation; either version 2 of the License, or
|
6
|
+
(at your option) any later version.
|
7
|
+
|
8
|
+
This program is distributed in the hope that it will be useful,
|
9
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
GNU General Public License for more details.
|
12
|
+
|
13
|
+
You should have received a copy of the GNU General Public License along
|
14
|
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
15
|
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
data/README
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
= What's this?
|
2
|
+
|
3
|
+
Arpie is a end-to-end framework for sending synchronous message-and-answer
|
4
|
+
pairs, and serves as the basis for a RPC framework, handling a variety of protocols,
|
5
|
+
including a generic Marshal proof of concept; writing your own Protocol is quite simple.
|
6
|
+
|
7
|
+
* It uses ruby threads on the server side, one per connection.
|
8
|
+
* The client is single-threaded.
|
9
|
+
|
10
|
+
== Source Code
|
11
|
+
|
12
|
+
Source code is in git[http://git.swordcoast.net/?p=lib/ruby/arpie.git;a=summary].
|
13
|
+
|
14
|
+
You can contact me via email at elven@swordcoast.net.
|
15
|
+
|
16
|
+
|
17
|
+
== Simple, contrived example: A string reverse server
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'arpie'
|
21
|
+
require 'socket'
|
22
|
+
|
23
|
+
server = TCPServer.new(51210)
|
24
|
+
|
25
|
+
e = Arpie::Endpoint.new(Arpie::MarshalProtocol.new)
|
26
|
+
|
27
|
+
e.handle do |ep, msg|
|
28
|
+
msg.reverse
|
29
|
+
end
|
30
|
+
|
31
|
+
e.accept do
|
32
|
+
server.accept
|
33
|
+
end
|
34
|
+
|
35
|
+
c = Arpie::Transport.new(Arpie::MarshalProtocol.new)
|
36
|
+
c.connect do |transport|
|
37
|
+
TCPSocket.new("127.0.0.1", 51210)
|
38
|
+
end
|
39
|
+
|
40
|
+
puts c.request "hi"
|
41
|
+
# => "ih"
|
42
|
+
|
43
|
+
== Advanced, but still simple example: Using Proxy to access remote objects
|
44
|
+
|
45
|
+
require 'rubygems'
|
46
|
+
require 'arpie'
|
47
|
+
require 'socket'
|
48
|
+
|
49
|
+
class MyHandler
|
50
|
+
def reverse str
|
51
|
+
str.reverse
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
server = TCPServer.new(51210)
|
56
|
+
|
57
|
+
e = Arpie::ProxyEndpoint.new(Arpie::MarshalProtocol.new)
|
58
|
+
|
59
|
+
e.handle MyHandler.new
|
60
|
+
|
61
|
+
e.accept do
|
62
|
+
server.accept
|
63
|
+
end
|
64
|
+
|
65
|
+
c = Arpie::Transport.new(Arpie::MarshalProtocol.new)
|
66
|
+
c.connect do |transport|
|
67
|
+
TCPSocket.new("127.0.0.1", 51210)
|
68
|
+
end
|
69
|
+
p = Arpie::Proxy.new(c)
|
70
|
+
|
71
|
+
puts p.reverse "hi"
|
72
|
+
# => "ih"
|
73
|
+
|
74
|
+
== Benchmarks
|
75
|
+
|
76
|
+
There is a benchmark script included in the git repository (and in the gem
|
77
|
+
under tools/). A sample output follows; your milage may vary.
|
78
|
+
|
79
|
+
user system total real
|
80
|
+
|
81
|
+
native DRb
|
82
|
+
1 0.000000 0.000000 0.000000 ( 0.000167)
|
83
|
+
1000 0.120000 0.010000 0.130000 ( 0.121834)
|
84
|
+
|
85
|
+
ruby xmlrpc/server - too slow to benchmark
|
86
|
+
|
87
|
+
Arpie: proxied MarshalProtocol
|
88
|
+
1 0.000000 0.000000 0.000000 ( 0.000617)
|
89
|
+
1000 0.100000 0.020000 0.120000 ( 0.114573)
|
data/Rakefile
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/clean"
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
require "rake/rdoctask"
|
5
|
+
require "fileutils"
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
##############################################################################
|
9
|
+
# Configuration
|
10
|
+
##############################################################################
|
11
|
+
NAME = "arpie"
|
12
|
+
VERS = "0.0.1"
|
13
|
+
CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage"]
|
14
|
+
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
15
|
+
"#{NAME}: A high-performing layered RPC framework. Simple to use, simple to extend.", \
|
16
|
+
'--main', 'README']
|
17
|
+
|
18
|
+
DOCS = ["README", "COPYING"]
|
19
|
+
|
20
|
+
Rake::RDocTask.new do |rdoc|
|
21
|
+
rdoc.rdoc_dir = "rdoc"
|
22
|
+
rdoc.options += RDOC_OPTS
|
23
|
+
rdoc.rdoc_files.add DOCS + ["doc/*.rdoc", "lib/**/*.rb"]
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Packages up #{NAME}"
|
27
|
+
task :package => [:clean]
|
28
|
+
|
29
|
+
spec = Gem::Specification.new do |s|
|
30
|
+
s.name = NAME
|
31
|
+
s.rubyforge_project = "#{NAME}"
|
32
|
+
s.version = VERS
|
33
|
+
s.platform = Gem::Platform::RUBY
|
34
|
+
s.has_rdoc = true
|
35
|
+
s.extra_rdoc_files = DOCS + Dir["doc/*.rdoc"]
|
36
|
+
s.rdoc_options += RDOC_OPTS + ["--exclude", "^(examples|extras)\/"]
|
37
|
+
s.summary = "a synchronous RPC library based on google protobuf"
|
38
|
+
s.description = s.summary
|
39
|
+
s.author = "Bernhard Stoeckner"
|
40
|
+
s.email = "elven@swordcoast.net"
|
41
|
+
s.homepage = "http://#{NAME}.elv.es"
|
42
|
+
s.executables = []
|
43
|
+
s.required_ruby_version = ">= 1.8.4"
|
44
|
+
s.files = %w(COPYING README Rakefile) + Dir.glob("{bin,doc,spec,lib,tools,scripts,data}/**/*")
|
45
|
+
s.require_path = "lib"
|
46
|
+
s.bindir = "bin"
|
47
|
+
end
|
48
|
+
|
49
|
+
Rake::GemPackageTask.new(spec) do |p|
|
50
|
+
p.need_tar = true
|
51
|
+
p.gem_spec = spec
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Install #{NAME} gem"
|
55
|
+
task :install do
|
56
|
+
sh %{rake package}
|
57
|
+
sh %{sudo gem1.8 install pkg/#{NAME}-#{VERS}}
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Regenerate proto classes"
|
61
|
+
task :protoc do
|
62
|
+
sh %{rprotoc --out=lib/arpie arpie.proto}
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Install #{NAME} gem without docs"
|
66
|
+
task :install_no_docs do
|
67
|
+
sh %{rake package}
|
68
|
+
sh %{sudo gem1.8 install pkg/#{NAME}-#{VERS} --no-rdoc --no-ri}
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "Uninstall #{NAME} gem"
|
72
|
+
task :uninstall => [:clean] do
|
73
|
+
sh %{sudo gem1.8 uninstall #{NAME}}
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "Upload #{NAME} gem to rubyforge"
|
77
|
+
task :release => [:package] do
|
78
|
+
sh %{rubyforge login}
|
79
|
+
sh %{rubyforge add_release #{NAME} #{NAME} #{VERS} pkg/#{NAME}-#{VERS}.tgz}
|
80
|
+
sh %{rubyforge add_file #{NAME} #{NAME} #{VERS} pkg/#{NAME}-#{VERS}.gem}
|
81
|
+
end
|
82
|
+
|
83
|
+
require "spec/rake/spectask"
|
84
|
+
|
85
|
+
desc "Run specs with coverage"
|
86
|
+
Spec::Rake::SpecTask.new("spec") do |t|
|
87
|
+
t.spec_files = FileList["spec/*_spec.rb"]
|
88
|
+
t.spec_opts = File.read("spec/spec.opts").split("\n")
|
89
|
+
t.rcov_opts = File.read("spec/rcov.opts").split("\n")
|
90
|
+
t.rcov = true
|
91
|
+
end
|
92
|
+
|
93
|
+
desc "Run specs without coverage"
|
94
|
+
task :default => [:spec_no_cov]
|
95
|
+
Spec::Rake::SpecTask.new("spec_no_cov") do |t|
|
96
|
+
t.spec_files = FileList["spec/*_spec.rb"]
|
97
|
+
t.spec_opts = File.read("spec/spec.opts").split("\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
desc "Run rcov only"
|
101
|
+
Spec::Rake::SpecTask.new("rcov") do |t|
|
102
|
+
t.rcov_opts = File.read("spec/rcov.opts").split("\n")
|
103
|
+
t.spec_opts = File.read("spec/spec.opts").split("\n")
|
104
|
+
t.spec_files = FileList["spec/*_spec.rb"]
|
105
|
+
t.rcov = true
|
106
|
+
end
|
107
|
+
|
108
|
+
desc "check documentation coverage"
|
109
|
+
task :dcov do
|
110
|
+
sh "find lib -name '*.rb' | xargs dcov"
|
111
|
+
end
|
data/lib/arpie.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module Arpie
|
2
|
+
|
3
|
+
# A Endpoint is the server-side part of a RPC setup.
|
4
|
+
# It accepts connections (via the acceptor), and handles
|
5
|
+
# incoming RPC calls on them.
|
6
|
+
#
|
7
|
+
# There will be one Thread per connection, so order of
|
8
|
+
# execution with multiple threads is not guaranteed.
|
9
|
+
class Endpoint
|
10
|
+
|
11
|
+
# Create a new Endpoint with the given +Protocol+.
|
12
|
+
# You will need to define a handler, and an acceptor
|
13
|
+
# before the endpoint becomes operational.
|
14
|
+
def initialize protocol
|
15
|
+
@protocol = protocol
|
16
|
+
@clients = []
|
17
|
+
|
18
|
+
@handler = lambda {|endpoint, message| raise ArgumentError, "No handler defined." }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Provide an acceptor; this will be run in a a loop
|
22
|
+
# to get IO objects.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
# listener = TCPServer.new(12345)
|
26
|
+
# my_endpoint.accept do
|
27
|
+
# listener.accept
|
28
|
+
# end
|
29
|
+
def accept &acceptor
|
30
|
+
@acceptor = acceptor
|
31
|
+
Thread.new { _acceptor_thread }
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set a message handler, which is a proc that will receive
|
35
|
+
# two parameters: the endpoint, and the message.
|
36
|
+
# Its return value will be sent as the reply.
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
# my_endpoint.handle do |endpoint, message|
|
40
|
+
# puts "Got a message: #{message.inspect}"
|
41
|
+
# "ok"
|
42
|
+
# end
|
43
|
+
def handle &handler
|
44
|
+
raise ArgumentError, "need a block" unless block_given?
|
45
|
+
@handler = handler
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def _handle message
|
51
|
+
@handler.call(self, message)
|
52
|
+
end
|
53
|
+
|
54
|
+
def _acceptor_thread
|
55
|
+
loop do
|
56
|
+
client = @acceptor.call(self)
|
57
|
+
@clients << client
|
58
|
+
Thread.new { _read_thread(client) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def _read_thread client
|
63
|
+
loop do
|
64
|
+
break if client.eof?
|
65
|
+
|
66
|
+
message, answer = nil, nil
|
67
|
+
begin
|
68
|
+
message = @protocol.read_message(client)
|
69
|
+
rescue => e
|
70
|
+
$stderr.puts "client went away while reading the message: #{e.to_s}"
|
71
|
+
break
|
72
|
+
end
|
73
|
+
|
74
|
+
begin
|
75
|
+
answer = _handle(message)
|
76
|
+
rescue Exception => e
|
77
|
+
$stderr.puts "Error in handler: #{e.message.to_s}"
|
78
|
+
$stderr.puts e.backtrace.join("\n")
|
79
|
+
$stderr.puts "Returning exception for this call."
|
80
|
+
answer = e
|
81
|
+
end
|
82
|
+
|
83
|
+
begin
|
84
|
+
@protocol.write_message(client, answer)
|
85
|
+
rescue => e
|
86
|
+
puts "client went away while writing the answer:: #{e.to_s}"
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
@clients.delete(client)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Arpie
|
2
|
+
|
3
|
+
# A Protocol converts messages (which are arbitary objects)
|
4
|
+
# to a suitable on-the-wire format, and back.
|
5
|
+
class Protocol
|
6
|
+
private_class_method :new
|
7
|
+
|
8
|
+
# Read a message from +io+. Block until a message
|
9
|
+
# has been received.
|
10
|
+
def read_message io
|
11
|
+
end
|
12
|
+
|
13
|
+
# Write a message to +io+.
|
14
|
+
def write_message io, message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# A sample binary protocol, upon which others can expand.
|
19
|
+
# The on the wire format is simply the data, prefixed
|
20
|
+
# with data.size.
|
21
|
+
class SizedProtocol < Protocol
|
22
|
+
def initialize
|
23
|
+
@max_message_size = 1024 * 1024
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_message io
|
27
|
+
sz = io.read(8)
|
28
|
+
expect = sz.unpack("Q")[0]
|
29
|
+
data = io.read(expect)
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_message io, message
|
33
|
+
io.write([message.size, message].pack("Qa*"))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# A procotol that simply Marshals all data sent over
|
38
|
+
# this protocol. Served as an example, but a viable
|
39
|
+
# choice for ruby-only production code.
|
40
|
+
class MarshalProtocol < SizedProtocol
|
41
|
+
public_class_method :new
|
42
|
+
|
43
|
+
def read_message io
|
44
|
+
Marshal.load super(io)
|
45
|
+
end
|
46
|
+
|
47
|
+
def write_message io, message
|
48
|
+
super io, Marshal.dump(message)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/arpie/proxy.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Arpie
|
2
|
+
|
3
|
+
# The RPC call encapsulation used by ProxyEndpoint and Proxy.
|
4
|
+
class ProxyCall < Struct.new(:method, :argv); end
|
5
|
+
|
6
|
+
# A Endpoint which supports arbitary objects as handlers,
|
7
|
+
# instead of a proc.
|
8
|
+
#
|
9
|
+
# Note that this will only export public instance method
|
10
|
+
# of the class as they are defined.
|
11
|
+
class ProxyEndpoint < Endpoint
|
12
|
+
def handle handler
|
13
|
+
@handler = handler
|
14
|
+
@interface = @handler.class.public_instance_methods(false)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def _handle message
|
20
|
+
@interface.index(message.method.to_s) or raise NoMethodError,
|
21
|
+
"Unknown method."
|
22
|
+
@handler.send(message.method, *message.argv)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# A Proxy is a wrapper around a transport, which transparently tunnels
|
27
|
+
# method calls to the remote ProxyEndpoint.
|
28
|
+
class Proxy
|
29
|
+
|
30
|
+
# Create a new Proxy.
|
31
|
+
def initialize transport
|
32
|
+
@transport = transport
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing method, *argv # :nodoc:
|
36
|
+
call = ProxyCall.new(method, argv)
|
37
|
+
ret = @transport.request(call)
|
38
|
+
case ret
|
39
|
+
when Exception
|
40
|
+
raise ret
|
41
|
+
else
|
42
|
+
ret
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Arpie
|
2
|
+
|
3
|
+
# A Transport is a connection manager, and acts as the
|
4
|
+
# glue between a user-defined medium (for example, a TCP
|
5
|
+
# socket), and a protocol.
|
6
|
+
#
|
7
|
+
# See README for examples.
|
8
|
+
class Transport
|
9
|
+
attr_reader :protocol
|
10
|
+
|
11
|
+
def initialize protocol
|
12
|
+
@protocol = protocol
|
13
|
+
@io = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
# Provide a connector block, which will be called
|
17
|
+
# each time a connection is needed.
|
18
|
+
# Set +connect_immediately+ to true to connect
|
19
|
+
# immediately, instead on the first message.
|
20
|
+
def connect connect_immediately = false, &connector
|
21
|
+
@connector = connector
|
22
|
+
_connect if connect_immediately
|
23
|
+
end
|
24
|
+
|
25
|
+
# Send a message and receive a reply.
|
26
|
+
def request message
|
27
|
+
_connect
|
28
|
+
@protocol.write_message(@io, message)
|
29
|
+
@protocol.read_message(@io)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def _connect
|
34
|
+
@io ||= @connector.call(self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/rcov.opts
ADDED
File without changes
|
data/spec/spec.opts
ADDED
File without changes
|
data/tools/benchmark.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'socket'
|
3
|
+
require 'arpie'
|
4
|
+
require 'benchmark'
|
5
|
+
require 'drb'
|
6
|
+
require 'xmlrpc/server'
|
7
|
+
require 'xmlrpc/client'
|
8
|
+
|
9
|
+
class Wrap
|
10
|
+
def reverse x
|
11
|
+
x.reverse
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
include Arpie
|
16
|
+
|
17
|
+
server = TCPServer.new(51210)
|
18
|
+
|
19
|
+
endpoint = ProxyEndpoint.new MarshalProtocol.new
|
20
|
+
endpoint.handle Wrap.new
|
21
|
+
|
22
|
+
endpoint.accept do
|
23
|
+
server.accept
|
24
|
+
end
|
25
|
+
|
26
|
+
$transport = Transport.new MarshalProtocol.new
|
27
|
+
$transport.connect(false) do |transport|
|
28
|
+
TCPSocket.new("127.0.0.1", 51210)
|
29
|
+
end
|
30
|
+
$proxy = Proxy.new $transport
|
31
|
+
|
32
|
+
Benchmark.bm {|b|
|
33
|
+
|
34
|
+
puts ""
|
35
|
+
puts "native DRb"
|
36
|
+
drbserver = DRb.start_service nil, Wrap.new
|
37
|
+
drbobject = DRbObject.new nil, DRb.uri
|
38
|
+
|
39
|
+
b.report(" 1") { 1.times { drbobject.reverse "benchmark" } }
|
40
|
+
b.report("1000") { 1000.times { drbobject.reverse "benchmark" } }
|
41
|
+
|
42
|
+
puts ""
|
43
|
+
puts "ruby xmlrpc/server - too slow to benchmark"
|
44
|
+
#server = XMLRPC::Server.new(51211, "127.0.0.1", 4, nil, false)
|
45
|
+
#server.add_handler(XMLRPC::iPIMethods("wrap"), Wrap.new)
|
46
|
+
#server_thread = Thread.new { server.serve }
|
47
|
+
#client = XMLRPC::Client.new( "127.0.0.1", "/", 51211)
|
48
|
+
#b.report(" 1") { 1.times { client.call("wrap.reverse", "benchmark") } }
|
49
|
+
#b.report("1000") { 1000.times { client.call("wrap.reverse", "benchmark") } }
|
50
|
+
#server.shutdown
|
51
|
+
#server_thread.join
|
52
|
+
|
53
|
+
puts ""
|
54
|
+
puts "Arpie: proxied MarshalProtocol"
|
55
|
+
b.report(" 1") { 1.times { $proxy.reverse "benchmark" } }
|
56
|
+
b.report("1000") { 1000.times { $proxy.reverse "benchmark" } }
|
57
|
+
}
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: arpie
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bernhard Stoeckner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-18 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: a synchronous RPC library based on google protobuf
|
17
|
+
email: elven@swordcoast.net
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- COPYING
|
25
|
+
files:
|
26
|
+
- COPYING
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- spec/spec.opts
|
30
|
+
- spec/rcov.opts
|
31
|
+
- lib/arpie.rb
|
32
|
+
- lib/arpie
|
33
|
+
- lib/arpie/protocol.rb
|
34
|
+
- lib/arpie/transport.rb
|
35
|
+
- lib/arpie/endpoint.rb
|
36
|
+
- lib/arpie/proxy.rb
|
37
|
+
- tools/benchmark.rb
|
38
|
+
has_rdoc: true
|
39
|
+
homepage: http://arpie.elv.es
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options:
|
42
|
+
- --quiet
|
43
|
+
- --line-numbers
|
44
|
+
- --inline-source
|
45
|
+
- --title
|
46
|
+
- "arpie: A high-performing layered RPC framework. Simple to use, simple to extend."
|
47
|
+
- --main
|
48
|
+
- README
|
49
|
+
- --exclude
|
50
|
+
- ^(examples|extras)/
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 1.8.4
|
58
|
+
version:
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project: arpie
|
68
|
+
rubygems_version: 1.3.0
|
69
|
+
signing_key:
|
70
|
+
specification_version: 2
|
71
|
+
summary: a synchronous RPC library based on google protobuf
|
72
|
+
test_files: []
|
73
|
+
|