pipe_rpc 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ad289824f7ad565af6f419ddf007c4bd1745e37
4
+ data.tar.gz: d6511143979b1c2a998eb3072042a596d264307e
5
+ SHA512:
6
+ metadata.gz: a13574ab492318a87acb1c82b5f74eb6a7a4e28e4022106725ce3c405de8a56528d08d54493386b0e5d4fb5e5a025d4d77577c3065aa0cea4081529076380542
7
+ data.tar.gz: eeeb48e3f988525d562d66a5cd64d3f88d7df8edef572f10d4df391b00a53616e7b08ed9935ccd05923b7321ff60fac816f091f15c0d0dfc1c59cd22335077a6
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ test.rb
data/.rakeTasks ADDED
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Settings><!--This file was automatically generated by Ruby plugin.
3
+ You are allowed to:
4
+ 1. Remove rake task
5
+ 2. Add existing rake tasks
6
+ To add existing rake tasks automatically delete this file and reload the project.
7
+ --><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build local_rpc-0.1.0.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Build and install local_rpc-0.1.0.gem into system gems" fullCmd="install" taksId="install" /><RakeTask description="Create tag v0.1.0 and build and push local_rpc-0.1.0.gem to Rubygems" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper.rb
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # PipeRpc
2
+
3
+ PipeRpc was designed so parent und child processes can call each other's methods. It uses a json protocol similar to JSON-RPC.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'pipe_rpc'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install pipe_rpc
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ require 'pipe_rpc'
25
+
26
+ request_read, request_write = IO.pipe
27
+ response_read, response_write = IO.pipe
28
+
29
+ pid = fork do
30
+ request_write.close
31
+ response_read.close
32
+
33
+ class Server
34
+ def add(a, b)
35
+ a + b
36
+ end
37
+ end
38
+
39
+ hub = PipeRpc::Hub.new(input: request_read, output: response_write)
40
+ hub.add_server(default: Server.new)
41
+
42
+ loop do
43
+ hub.handle_message # blocks until message available
44
+ end
45
+ end
46
+
47
+ begin
48
+ request_read.close
49
+ response_write.close
50
+
51
+ hub = PipeRpc::Hub.new(output: request_write, input: response_read)
52
+ client = hub.client_for(:default)
53
+
54
+ puts client.add(3, 5)
55
+ ensure
56
+ Process.kill 9, pid
57
+ Process.wait pid
58
+ end
59
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/lib/hash.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def symbolize_keys
3
+ Hash[self.map{ |k,v| [(k.to_sym rescue k), v] }]
4
+ end
5
+ end
@@ -0,0 +1,30 @@
1
+ module PipeRpc
2
+ class Client < BasicObject
3
+ def initialize(hub, args = {})
4
+ @hub = hub
5
+ @server = args.fetch(:server, :default).to_sym
6
+ end
7
+
8
+ def method_missing(method, *args)
9
+ backtrace = ::Kernel.respond_to?(:caller) ? ::Kernel.caller(1) : []
10
+
11
+ @hub.request(server: @server, method: method, arguments: args) do |result|
12
+ if result.is_a? ::StandardError
13
+ result.set_backtrace(result.backtrace.to_a + backtrace.to_a) if result.respond_to? :set_backtrace
14
+ ::Kernel.raise result
15
+ else
16
+ result
17
+ end
18
+ end
19
+ # Method won't return until we got a result because @hub.request starts a loop and blocks!
20
+ end
21
+
22
+ def to_s
23
+ "<Client:#{@server.to_s}>"
24
+ end
25
+
26
+ def is_a?(object)
27
+ object == Client
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,6 @@
1
+ module PipeRpc
2
+ class Error < RuntimeError; end
3
+ class InternalError < Error; end
4
+ class NoServerError < Error; end
5
+ class ReflectedError < Error; end
6
+ end
@@ -0,0 +1,77 @@
1
+ module PipeRpc
2
+ class ErrorResponse
3
+ def initialize(args = {})
4
+ @id = args.fetch(:id, nil)
5
+ error = args.fetch(:error)
6
+ @code = error.fetch(:code)
7
+ @message = msg_for(@code) || error.fetch(:message, 'Unknown error')
8
+ @data = error.fetch(:data, nil)
9
+ end
10
+
11
+ attr_reader :id, :code, :message, :data
12
+
13
+ def to_h
14
+ { id: id, error: { code: code, message: message, data: data } }
15
+ end
16
+
17
+ def native_error(request = nil)
18
+ @request = request
19
+ error_for(@code)
20
+ end
21
+
22
+ def result_for(*args)
23
+ native_error(*args)
24
+ end
25
+
26
+ private
27
+
28
+ def msg_for(code)
29
+ case code
30
+ when -32700 then 'Parse error'
31
+ when -32600 then 'Invalid Request'
32
+ when -32601 then 'Method not found'
33
+ when -32602 then 'Invalid arguments'
34
+ when -32603 then 'Internal error'
35
+ when -32604 then 'Server not found'
36
+ when -32605 then 'Reflected error'
37
+ else nil
38
+ end
39
+ end
40
+
41
+ def error_for(code)
42
+ case code
43
+ when -32601 then no_method_error
44
+ when -32602 then argument_error
45
+ when -32604 then no_server_error
46
+ when -32605 then reflected_error
47
+ else internal_error
48
+ end
49
+ end
50
+
51
+ def no_method_error
52
+ method = @data.fetch(:method)
53
+ args = @data.fetch(:args)
54
+ NoMethodError.new("undefined method `#{method}' for <Client:#{@request.server}>", method, args)
55
+ end
56
+
57
+ def argument_error
58
+ ArgumentError.new(@data.fetch(:message))
59
+ end
60
+
61
+ def no_server_error
62
+ NoServerError.new("undefined server `#{@request.server}'")
63
+ end
64
+
65
+ def internal_error
66
+ InternalError.new("#{@data[:message]}").tap do |error|
67
+ error.set_backtrace(@data[:backtrace]) if error.respond_to? :set_backtrace
68
+ end
69
+ end
70
+
71
+ def reflected_error
72
+ ReflectedError.new("#{@data[:message]}").tap do |error|
73
+ error.set_backtrace(@data[:backtrace]) if error.respond_to? :set_backtrace
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,57 @@
1
+ module PipeRpc
2
+ class Hub
3
+ class Message
4
+ def initialize(hub, message)
5
+ @hub = hub
6
+ @message = message
7
+ end
8
+
9
+ def notification?
10
+ @message.has_key? :method and not id?
11
+ end
12
+
13
+ def request?
14
+ @message.has_key? :method and id?
15
+ end
16
+
17
+ def response?
18
+ (result? or error_message?) and id?
19
+ end
20
+
21
+ def error?
22
+ error_message? and not id?
23
+ end
24
+
25
+ def handler
26
+ @handler ||= type.new(@message)
27
+ rescue => e
28
+ @hub.send_error(id: nil, code: -32600, data: { message: e.message })
29
+ nil
30
+ end
31
+
32
+ private
33
+
34
+ def result?
35
+ @message.has_key? :result
36
+ end
37
+
38
+ def error_message?
39
+ @message.has_key? :error
40
+ end
41
+
42
+ def type
43
+ if error_message?
44
+ ErrorResponse
45
+ elsif result?
46
+ ResultResponse
47
+ else
48
+ Request
49
+ end
50
+ end
51
+
52
+ def id?
53
+ not @message[:id].nil?
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,31 @@
1
+ module PipeRpc
2
+ class Hub
3
+ class Requester
4
+ def initialize(hub)
5
+ @hub = hub
6
+ @requests = {}
7
+ @uid = 0
8
+ end
9
+
10
+ def next_uid
11
+ @uid += 1
12
+ end
13
+
14
+ def notification(signature)
15
+ Request.new(signature)
16
+ end
17
+
18
+ def request(signature, &on_response)
19
+ request = Request.new(signature.merge(id: next_uid))
20
+ @requests[request.id] = { request: request, on_response: on_response }
21
+ request
22
+ end
23
+
24
+ def handle_response(response)
25
+ request = @requests.delete(response.id)
26
+ raise InternalError.new("no request for response(id: #{response.id})") unless request
27
+ request[:on_response].call response.result_for(request[:request])
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,90 @@
1
+ module PipeRpc
2
+ class Hub
3
+ class Responder
4
+ def initialize(hub)
5
+ @hub = hub
6
+ @servers = {}
7
+ end
8
+
9
+ def add_server(servers)
10
+ servers.each{ |name, server| @servers[name.to_sym] = server }
11
+ end
12
+
13
+ def rmv_server(server_name)
14
+ @servers.delete(server_name.to_sym)
15
+ end
16
+
17
+ def on_request(&on_request)
18
+ @on_request = on_request
19
+ end
20
+
21
+ def handle_notification(notification)
22
+ handle_request(notification) {}
23
+ end
24
+
25
+ def handle_request(request, &on_result)
26
+ id, server, method, args = request.id, @servers[request.server], request.method, request.arguments
27
+
28
+ unless server
29
+ @hub.send_error(id: id, code: -32604)
30
+ return
31
+ end
32
+
33
+ async = proc do |result|
34
+ on_result.call ResultResponse.new(id: id, result: result)
35
+ end
36
+
37
+ @on_request.call(server, method, args) if @on_request
38
+
39
+ # methods returning the async block as result state that they are asynchronous!
40
+ method_lineno = __LINE__+1
41
+ result = server.__send__(method, *args, &async)
42
+
43
+ # directly return result for synchronous calls
44
+ async.call(result) unless result == async
45
+
46
+ rescue NoMethodError => e
47
+ backtrace = e.backtrace.to_a
48
+ code = itself_caused_no_method_error?(backtrace, method_lineno) ? -32601 : -32603
49
+ @hub.send_error(id: id, code: code, data: { message: e.message, method: e.name,
50
+ args: e.args, backtrace: backtrace })
51
+
52
+ rescue ArgumentError => e
53
+ backtrace = e.backtrace.to_a
54
+ code = itself_caused_argument_error?(backtrace, method_lineno) ? -32602 : -32603
55
+ @hub.send_error(id: id, code: code, data: { message: e.message, backtrace: backtrace })
56
+
57
+ rescue InternalError => e # raised on the other side
58
+ backtrace = e.backtrace.to_a
59
+ @hub.send_error(id: id, code: -32605, data: { message: e.message, backtrace: backtrace })
60
+
61
+ rescue => e
62
+ backtrace = e.backtrace.to_a
63
+ @hub.send_error(id: id, code: -32603, data: { message: e.message, backtrace: backtrace })
64
+ end
65
+
66
+ private
67
+
68
+ def itself_caused_no_method_error?(backtrace, ref_lineno)
69
+ if Object.const_defined?(:MRUBY_VERSION)
70
+ !backtrace[0]
71
+ else
72
+ itself_caused_error?(backtrace[0], ref_lineno)
73
+ end
74
+ end
75
+
76
+ def itself_caused_argument_error?(backtrace, ref_lineno)
77
+ if Object.const_defined?(:MRUBY_VERSION)
78
+ !backtrace[0]
79
+ else
80
+ itself_caused_error?(backtrace[1], ref_lineno)
81
+ end
82
+ end
83
+
84
+ def itself_caused_error?(backtrace_loc, ref_lineno)
85
+ file, lineno, = backtrace_loc.split(':')
86
+ (file == __FILE__) and (lineno.to_i == ref_lineno)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,104 @@
1
+ module PipeRpc
2
+ class Hub
3
+ def initialize(args)
4
+ @channel = args[:input]
5
+ @socket = Socket.new(self, args)
6
+ @requester = Requester.new(self)
7
+ @responder = Responder.new(self)
8
+ @clients = {}
9
+ self.loop_iteration = nil
10
+ end
11
+
12
+ attr_reader :channel
13
+ attr_accessor :logger
14
+
15
+ def log(msg)
16
+ if logger == :reflect
17
+ notify(server: :reflect_logger, method: :log, arguments: [msg])
18
+ elsif logger.respond_to? :debug
19
+ logger.debug msg
20
+ elsif logger
21
+ logger.call msg
22
+ end
23
+ end
24
+
25
+ def add_server(servers)
26
+ @responder.add_server(servers)
27
+ end
28
+
29
+ def rmv_server(server_name)
30
+ @responder.rmv_server(server_name)
31
+ end
32
+
33
+ def on_incoming_request(&on_request)
34
+ @responder.on_request(&on_request)
35
+ end
36
+
37
+ def client_for(server_name)
38
+ @clients[server_name] ||= Client.new(self, server: server_name)
39
+ end
40
+
41
+ def loop_iteration=(proc)
42
+ @loop_iteration = proc
43
+ end
44
+
45
+ def on_sent(&on_sent)
46
+ @socket.on_write(&on_sent)
47
+ end
48
+
49
+ def on_received(&on_received)
50
+ @socket.on_read(&on_received)
51
+ end
52
+
53
+ def notify(signature)
54
+ @socket.write @requester.notification(signature)
55
+ end
56
+
57
+ def request(signature, &on_result)
58
+ result = nil
59
+ result_ready = false
60
+
61
+ request = @requester.request(signature) do |*response|
62
+ result = on_result.call(*response)
63
+ result_ready = true
64
+ end
65
+ @socket.write request
66
+
67
+ loop do
68
+ return result if result_ready
69
+ @loop_iteration ? @loop_iteration.call : handle_message
70
+ end
71
+ end
72
+
73
+ def send_error(error = {})
74
+ @socket.write ErrorResponse.new(id: error.delete(:id), error: error)
75
+ end
76
+
77
+ def handle_message
78
+ message = next_message # blocks
79
+
80
+ return unless message
81
+
82
+ if message.notification?
83
+ @responder.handle_notification(message.handler)
84
+ elsif message.request?
85
+ @responder.handle_request(message.handler) { |response| @socket.write response }
86
+ elsif message.response?
87
+ @requester.handle_response(message.handler)
88
+ elsif message.error?
89
+ raise message.handler.native_error
90
+ else
91
+ send_error(id: nil, code: -32600, data: { message: 'no request, result or error' })
92
+ end
93
+ end
94
+
95
+ private
96
+
97
+ def next_message
98
+ Message.new(self, @socket.read) # blocks
99
+ rescue => e
100
+ send_error(id: nil, code: -32700, data: { message: e.message })
101
+ nil
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,16 @@
1
+ module PipeRpc
2
+ class Request
3
+ def initialize(args)
4
+ @server = args.fetch(:server, :default).to_sym
5
+ @method = args.fetch(:method).to_sym
6
+ @arguments = args.fetch(:arguments, [])
7
+ @id = args.fetch(:id, nil)
8
+ end
9
+
10
+ attr_reader :server, :method, :arguments, :id
11
+
12
+ def to_h
13
+ { server: server, method: method, arguments: arguments, id: id }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ module PipeRpc
2
+ class ResultResponse
3
+ def initialize(args = {})
4
+ @result = sanitize(args.fetch(:result))
5
+ @id = args.fetch(:id)
6
+ end
7
+
8
+ attr_reader :result, :id
9
+
10
+ def result_for(request)
11
+ result
12
+ end
13
+
14
+ def to_h
15
+ { id: id, result: result }
16
+ end
17
+
18
+ private
19
+
20
+ def sanitize(result)
21
+ if true == result or false == result or nil == result or result.is_a?(String) or result.is_a?(Numeric)
22
+ result
23
+ elsif result.is_a?(Array)
24
+ result.map{ |v| sanitize(v) }
25
+ elsif result.is_a?(Hash)
26
+ Hash[result.map{ |k,v| [sanitize(k), sanitize(v)] }]
27
+ else
28
+ result.to_s
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ module PipeRpc
2
+ class Socket
3
+ def initialize(hub, args = {})
4
+ @hub = hub
5
+ @input = args.fetch(:input)
6
+ @output = args.fetch(:output)
7
+ on_write{}
8
+ on_read{}
9
+ end
10
+
11
+ def read
12
+ symbolize_message_keys(JSON.load(@input.gets)).tap do |message|
13
+ next if message[:server] == 'reflect_logger'
14
+ @hub.log "received: #{message.inspect}"
15
+ @on_read.call(message)
16
+ end
17
+ end
18
+
19
+ def write(obj)
20
+ raise InternalError.new('Output pipe broke') if @output.closed?
21
+ @output.puts(JSON.dump(obj.to_h.tap do |message|
22
+ next if @hub.logger == :reflect
23
+ @hub.log "sent: #{message.inspect}"
24
+ @on_write.call(message)
25
+ end))
26
+ end
27
+
28
+ def on_write(&on_write)
29
+ @on_write = on_write || proc{}
30
+ end
31
+
32
+ def on_read(&on_read)
33
+ @on_read = on_read || proc{}
34
+ end
35
+
36
+ private
37
+
38
+ def symbolize_message_keys(message)
39
+ hash = message.symbolize_keys
40
+ hash[:error] = hash[:error].symbolize_keys if hash[:error]
41
+ hash[:error][:data] = hash[:error][:data].symbolize_keys if hash[:error] and hash[:error][:data]
42
+ hash
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module PipeRpc
2
+ VERSION = "0.2.0"
3
+ end
data/lib/pipe_rpc.rb ADDED
@@ -0,0 +1,16 @@
1
+ module PipeRpc
2
+ end
3
+
4
+ require 'json'
5
+ require_relative 'hash'
6
+ require_relative "pipe_rpc/version"
7
+ require_relative "pipe_rpc/error"
8
+ require_relative "pipe_rpc/request"
9
+ require_relative "pipe_rpc/result_response"
10
+ require_relative "pipe_rpc/error_response"
11
+ require_relative "pipe_rpc/socket"
12
+ require_relative "pipe_rpc/client"
13
+ require_relative "pipe_rpc/hub"
14
+ require_relative "pipe_rpc/hub/message"
15
+ require_relative "pipe_rpc/hub/requester"
16
+ require_relative "pipe_rpc/hub/responder"
data/pipe_rpc.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pipe_rpc/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pipe_rpc"
8
+ spec.version = PipeRpc::VERSION
9
+ spec.authors = ["Christopher Aue"]
10
+ spec.email = ["mail@christopheraue.net"]
11
+
12
+ spec.summary = %q{RPC between parent and child process over pipes}
13
+ spec.description = %q{PipeRpc was designed so parent und child processes can call each other's
14
+ methods. It uses a json protocol similar to JSON-RPC.}
15
+ spec.homepage = "https://github.com/christopheraue/ruby-pipe_rpc"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "json"
23
+ spec.add_development_dependency "bundler", "~> 1.8"
24
+ spec.add_development_dependency "rspec", "~> 3.4"
25
+ spec.add_development_dependency "rspec-its"
26
+ spec.add_development_dependency "rspec-mocks-matchers-send_message", "~> 0.2"
27
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pipe_rpc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Aue
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-its
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-mocks-matchers-send_message
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.2'
83
+ description: |-
84
+ PipeRpc was designed so parent und child processes can call each other's
85
+ methods. It uses a json protocol similar to JSON-RPC.
86
+ email:
87
+ - mail@christopheraue.net
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".rakeTasks"
94
+ - ".rspec"
95
+ - ".travis.yml"
96
+ - Gemfile
97
+ - README.md
98
+ - Rakefile
99
+ - lib/hash.rb
100
+ - lib/pipe_rpc.rb
101
+ - lib/pipe_rpc/client.rb
102
+ - lib/pipe_rpc/error.rb
103
+ - lib/pipe_rpc/error_response.rb
104
+ - lib/pipe_rpc/hub.rb
105
+ - lib/pipe_rpc/hub/message.rb
106
+ - lib/pipe_rpc/hub/requester.rb
107
+ - lib/pipe_rpc/hub/responder.rb
108
+ - lib/pipe_rpc/request.rb
109
+ - lib/pipe_rpc/result_response.rb
110
+ - lib/pipe_rpc/socket.rb
111
+ - lib/pipe_rpc/version.rb
112
+ - pipe_rpc.gemspec
113
+ homepage: https://github.com/christopheraue/ruby-pipe_rpc
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.4.5.1
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: RPC between parent and child process over pipes
137
+ test_files: []