farcall 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/README.md +57 -36
- data/farcall.gemspec +1 -0
- data/lib/farcall.rb +6 -0
- data/lib/farcall/boss_transport.rb +52 -0
- data/lib/farcall/json_transport.rb +13 -7
- data/lib/farcall/transport.rb +6 -1
- data/lib/farcall/version.rb +1 -1
- data/spec/endpoint_spec.rb +12 -5
- data/spec/rmi_spec.rb +7 -0
- data/spec/transports_spec.rb +24 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00f92b591c51a5eed01bd1bf156d902e4865ec4f
|
4
|
+
data.tar.gz: 741af581d714a7e6b435941a9f2e1b1946361ed2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8da68133b9dbf39cc77e11287b6bc491a0bdbecac048b8bfd94f02e88a521bd9e6360755a89060da73ef40d02efb61c85ff45d4cb4cfe495c232192780abd65e
|
7
|
+
data.tar.gz: 5af5f225af489f8c6aa75cc880d6855a45991f1baf500b4072af75cdd80286f1ce4625c781579b89f64a66244a20cdca257a080e410cf63d0d8c48b8c699ce58
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,46 +2,74 @@
|
|
2
2
|
|
3
3
|
## Important!
|
4
4
|
|
5
|
-
The gem creation is under active development, current state is: beta.
|
5
|
+
The gem creation is under active development, current state is: beta. The JSON and
|
6
|
+
(BOSS)[https://github.com/sergeych/boss_protocol] formats are supported out of the box,
|
7
|
+
thogh XML and other could be easily implemented.
|
6
8
|
|
7
9
|
## Description
|
8
10
|
|
9
11
|
The simple and elegant cross-platform RPC protocol that uses any formatter/transport capable of
|
10
|
-
transmitting dictionary-like objects, for example, JSON, XML, BSON, BOSS and many others.
|
12
|
+
transmitting dictionary-like objects, for example, JSON, XML, BSON, BOSS and many others. This gem
|
13
|
+
supports out of the box JSON and (BOSS)[https://github.com/sergeych/boss_protocol] protocols.
|
11
14
|
|
12
15
|
RPC is made asynchronously, each call can have any return values. While one call is waiting,
|
13
16
|
other calls can be executed. The protocol is bidirectional Call parameters could be
|
14
17
|
both arrays of arguments and keyword arguments, return value could be any object, e.g. array,
|
15
18
|
dictionary, wahtever.
|
16
19
|
|
17
|
-
Exception/errors transmitting is also supported.
|
20
|
+
Exception/errors transmitting is also supported. The interface is very simple and rubyish. The
|
21
|
+
protocol is very easy to support, its description will be available in the github wiki soon.
|
18
22
|
|
19
|
-
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
Add this line to your application's Gemfile:
|
20
26
|
|
21
27
|
```ruby
|
22
|
-
|
23
|
-
#
|
24
|
-
|
28
|
+
gem 'farcall'
|
29
|
+
# If you want to use binary-effective boss encoding:
|
30
|
+
# gem 'noss-protocol', '>= 1.4.1'
|
31
|
+
```
|
25
32
|
|
26
|
-
|
33
|
+
And then execute:
|
27
34
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
return "Foo: #{a+b}, #{optional}"
|
32
|
-
end
|
33
|
-
end
|
35
|
+
$ bundle
|
36
|
+
|
37
|
+
Or install it yourself as:
|
34
38
|
|
35
|
-
|
39
|
+
$ gem install farcall
|
36
40
|
|
37
|
-
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
|
45
|
+
# The sample class that exports all its methods to the remote callers:
|
46
|
+
#
|
47
|
+
class TestProvider < Farcall::Provider
|
48
|
+
|
49
|
+
attr :foo_calls, :a, :b
|
50
|
+
|
51
|
+
def foo a, b, optional: 'none'
|
52
|
+
@foo_calls = (@foo_calls || 0) + 1
|
53
|
+
@a, @b = a, b
|
54
|
+
return "Foo: #{a+b}, #{optional}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# create instance and export it to some connected socket:
|
59
|
+
TestProvider.new socket: connected_socket # default format is JSON
|
60
|
+
|
61
|
+
# or using boss, if you need to pass dates and binary data
|
62
|
+
TestProvider.new socket: connected_socket, format: :boss
|
38
63
|
```
|
39
64
|
|
40
65
|
Suppose whe have some socket connected to one above, then TestProvider methods are available via
|
41
66
|
this connection:
|
42
67
|
|
43
68
|
```ruby
|
69
|
+
|
44
70
|
i = Farcall::Interface.new socket: client_socket
|
71
|
+
# or
|
72
|
+
# i = Farcall::Interface.new socket: client_socket, format: :boss
|
45
73
|
|
46
74
|
# Plain arguments
|
47
75
|
i.foo(10, 20).should == 'Foo: 30, none'
|
@@ -57,30 +85,23 @@ this connection:
|
|
57
85
|
i.b.should == 6
|
58
86
|
```
|
59
87
|
|
60
|
-
|
61
|
-
|
62
|
-
Add this line to your application's Gemfile:
|
63
|
-
|
64
|
-
```ruby
|
65
|
-
gem 'farcall'
|
66
|
-
```
|
67
|
-
|
68
|
-
And then execute:
|
69
|
-
|
70
|
-
$ bundle
|
71
|
-
|
72
|
-
Or install it yourself as:
|
73
|
-
|
74
|
-
$ gem install farcall
|
88
|
+
More creation options ofr both provider and interface creation are:
|
75
89
|
|
76
|
-
|
90
|
+
* `endpoint:` at this point please refrain of using it as endpoint interface is going to change a
|
91
|
+
bit
|
92
|
+
* `transport:` subclass the `Farcall::Transport` and provide your own. It overrides `socket:`,
|
93
|
+
`input:` and `ouput:` parameters.
|
94
|
+
* `input:` and `output:` should be presented both or none - override `socket` - provide streams to
|
95
|
+
build the transport over.
|
96
|
+
|
77
97
|
|
78
|
-
|
98
|
+
Get more in (online docs)[http://www.rubydoc.info/gems/farcall]
|
79
99
|
|
80
100
|
## Contributing
|
81
101
|
|
82
102
|
1. Fork it ( https://github.com/[my-github-username]/farcall/fork )
|
83
103
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
84
|
-
3.
|
85
|
-
4.
|
86
|
-
5.
|
104
|
+
3. Do not forget ot add specs and ensure all of them pass
|
105
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
106
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
107
|
+
6. Create a new Pull Request
|
data/farcall.gemspec
CHANGED
data/lib/farcall.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
+
|
1
2
|
require 'farcall/version'
|
2
3
|
require 'farcall/transport'
|
3
4
|
require 'farcall/json_transport'
|
4
5
|
require 'farcall/endpoint'
|
6
|
+
begin
|
7
|
+
require 'boss-protocol'
|
8
|
+
require 'farcall/boss_transport'
|
9
|
+
rescue LoadError
|
10
|
+
end
|
5
11
|
|
6
12
|
module Farcall
|
7
13
|
# Your code goes here...
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Farcall
|
2
|
+
|
3
|
+
class BossTransport < Farcall::Transport
|
4
|
+
include TransportBase
|
5
|
+
|
6
|
+
# Create json transport, see Farcall::Transpor#create for parameters
|
7
|
+
def initialize **params
|
8
|
+
setup_streams **params
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_data_received= block
|
12
|
+
super
|
13
|
+
if block && !@thread
|
14
|
+
@thread = Thread.start {
|
15
|
+
load_loop
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_data hash
|
21
|
+
@output << Boss.dump(hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
def close
|
25
|
+
if !@closing
|
26
|
+
@closing = true
|
27
|
+
close_connection
|
28
|
+
@thread and @thread.join
|
29
|
+
@thread = nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def load_loop
|
36
|
+
Boss::Parser.new(@input).each { |object|
|
37
|
+
on_data_received and on_data_received.call object
|
38
|
+
}
|
39
|
+
rescue Errno::EPIPE
|
40
|
+
close
|
41
|
+
rescue
|
42
|
+
if !@closing
|
43
|
+
STDERR.puts "Farcall::BossTransport read loop failed: #{$!.class.name}: #$!"
|
44
|
+
STDERR.puts $!.backtrace.join("\n")
|
45
|
+
connection_aborted $!
|
46
|
+
else
|
47
|
+
close
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'json'
|
2
|
+
require 'socket'
|
2
3
|
|
3
4
|
module Farcall
|
4
5
|
|
@@ -10,17 +11,22 @@ module Farcall
|
|
10
11
|
end
|
11
12
|
|
12
13
|
def read length=1
|
13
|
-
data = ''
|
14
|
-
while data.length < length
|
15
|
-
|
16
|
-
end
|
17
|
-
data
|
14
|
+
# data = ''
|
15
|
+
# while data.length < length
|
16
|
+
# data << @socket.recv(length - data.length, Socket::MSG_WAITALL)
|
17
|
+
# end
|
18
|
+
# data
|
19
|
+
@socket.read length
|
18
20
|
end
|
19
21
|
|
20
22
|
def write data
|
21
23
|
@socket.write data
|
22
24
|
end
|
23
25
|
|
26
|
+
def eof?
|
27
|
+
@socket.eof?
|
28
|
+
end
|
29
|
+
|
24
30
|
def << data
|
25
31
|
write data
|
26
32
|
end
|
@@ -110,7 +116,6 @@ module Farcall
|
|
110
116
|
close_connection
|
111
117
|
@thread and @thread.join
|
112
118
|
@thread = nil
|
113
|
-
@in_close = false
|
114
119
|
end
|
115
120
|
end
|
116
121
|
|
@@ -118,7 +123,7 @@ module Farcall
|
|
118
123
|
|
119
124
|
def load_loop
|
120
125
|
buffer = ''
|
121
|
-
while
|
126
|
+
while !@input.eof?
|
122
127
|
buffer << @input.read(1)
|
123
128
|
if buffer[@dlength..-1] == @delimiter
|
124
129
|
on_data_received and on_data_received.call(JSON.parse(buffer[0...@dlength]))
|
@@ -130,6 +135,7 @@ module Farcall
|
|
130
135
|
rescue
|
131
136
|
if !@closing
|
132
137
|
STDERR.puts "Farcall::JsonTransport read loop failed: #{$!.class.name}: #$!"
|
138
|
+
STDERR.puts $!.backtrace.join("\n")
|
133
139
|
connection_aborted $!
|
134
140
|
else
|
135
141
|
close
|
data/lib/farcall/transport.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module Farcall
|
3
2
|
|
4
3
|
# Generic error in Farcall library
|
@@ -35,6 +34,12 @@ module Farcall
|
|
35
34
|
case format
|
36
35
|
when :json
|
37
36
|
Farcall::JsonTransport.new **params
|
37
|
+
when :boss
|
38
|
+
if defined?(Farcall::BossTransport)
|
39
|
+
Farcall::BossTransport.new **params
|
40
|
+
else
|
41
|
+
raise Farcall::Error.new("add gem 'boss-protocol' to use boss transport")
|
42
|
+
end
|
38
43
|
else
|
39
44
|
raise Farcall::Error, "unknown format: #{format}"
|
40
45
|
end
|
data/lib/farcall/version.rb
CHANGED
data/spec/endpoint_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'stringio'
|
3
2
|
|
4
3
|
# The sample class that exports all its methods to the remote callers:
|
5
4
|
#
|
@@ -14,6 +13,7 @@ class TestProvider < Farcall::Provider
|
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
16
|
+
|
17
17
|
describe 'endpoint' do
|
18
18
|
include Farcall
|
19
19
|
|
@@ -41,12 +41,11 @@ describe 'endpoint' do
|
|
41
41
|
ib.split.should == ['Hello', 'world']
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
def check_protocol format
|
45
45
|
s1, s2 = Socket.pair(:UNIX, :STREAM, 0)
|
46
46
|
|
47
|
-
tp = TestProvider.new socket: s1, format:
|
48
|
-
i
|
49
|
-
|
47
|
+
tp = TestProvider.new socket: s1, format: format
|
48
|
+
i = Farcall::Interface.new socket: s2, format: format, provider: "Hello world"
|
50
49
|
|
51
50
|
expect(-> { i.foo() }).to raise_error Farcall::RemoteError
|
52
51
|
|
@@ -59,4 +58,12 @@ describe 'endpoint' do
|
|
59
58
|
tp.far_interface.split.should == ['Hello', 'world']
|
60
59
|
end
|
61
60
|
|
61
|
+
it 'should connect json via shortcut' do
|
62
|
+
check_protocol :json
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should connect boss via shortcut' do
|
66
|
+
check_protocol :boss
|
67
|
+
end
|
68
|
+
|
62
69
|
end
|
data/spec/rmi_spec.rb
ADDED
data/spec/transports_spec.rb
CHANGED
@@ -70,5 +70,29 @@ describe 'transports' do
|
|
70
70
|
results.should == [{ 'echo' => { 'foo' => 'bar' } }, { 'echo' => { 'one' => 2 } }]
|
71
71
|
end
|
72
72
|
|
73
|
+
it 'should run boss transport' do
|
74
|
+
s1, s2 = Socket.pair(:UNIX, :STREAM, 0)
|
75
|
+
|
76
|
+
j1 = Farcall::BossTransport.new socket: s1
|
77
|
+
j2 = Farcall::BossTransport.new socket: s2
|
78
|
+
|
79
|
+
j2.receive_data { |data|
|
80
|
+
j2.send_data({ echo: data })
|
81
|
+
}
|
82
|
+
|
83
|
+
results = []
|
84
|
+
j1.receive_data { |data|
|
85
|
+
results << data
|
86
|
+
}
|
87
|
+
|
88
|
+
j1.send_data({ foo: "bar" })
|
89
|
+
j1.send_data({ one: 2 })
|
90
|
+
sleep 0.01
|
91
|
+
j1.close
|
92
|
+
j2.close
|
93
|
+
|
94
|
+
results.should == [{ 'echo' => { 'foo' => 'bar' } }, { 'echo' => { 'one' => 2 } }]
|
95
|
+
end
|
96
|
+
|
73
97
|
|
74
98
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: farcall
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sergeych
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: boss-protocol
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.4.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.4.1
|
55
69
|
description: |-
|
56
70
|
Can work with any transpot capable of conveing dictionaries (json, xml, bson, boss, yaml.
|
57
71
|
Incides some transports.
|
@@ -69,11 +83,13 @@ files:
|
|
69
83
|
- Rakefile
|
70
84
|
- farcall.gemspec
|
71
85
|
- lib/farcall.rb
|
86
|
+
- lib/farcall/boss_transport.rb
|
72
87
|
- lib/farcall/endpoint.rb
|
73
88
|
- lib/farcall/json_transport.rb
|
74
89
|
- lib/farcall/transport.rb
|
75
90
|
- lib/farcall/version.rb
|
76
91
|
- spec/endpoint_spec.rb
|
92
|
+
- spec/rmi_spec.rb
|
77
93
|
- spec/spec_helper.rb
|
78
94
|
- spec/transports_spec.rb
|
79
95
|
homepage: ''
|
@@ -102,5 +118,6 @@ specification_version: 4
|
|
102
118
|
summary: Simple, elegant and cross-platofrm RCP and RMI protocol
|
103
119
|
test_files:
|
104
120
|
- spec/endpoint_spec.rb
|
121
|
+
- spec/rmi_spec.rb
|
105
122
|
- spec/spec_helper.rb
|
106
123
|
- spec/transports_spec.rb
|