marilyn-rpc 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENCE +18 -0
- data/README.md +170 -0
- data/doc/MarilynRPC/CallRequestMail.html +578 -0
- data/doc/MarilynRPC/CallResponseMail.html +418 -0
- data/doc/MarilynRPC/Envelope.html +705 -0
- data/doc/MarilynRPC/ExceptionMail.html +338 -0
- data/doc/MarilynRPC/Gentleman.html +658 -0
- data/doc/MarilynRPC/MailFactory.html +284 -0
- data/doc/MarilynRPC/MailHelper.html +489 -0
- data/doc/MarilynRPC/NativeClient.html +579 -0
- data/doc/MarilynRPC/NativeClientProxy.html +303 -0
- data/doc/MarilynRPC/Server.html +406 -0
- data/doc/MarilynRPC/Service.html +599 -0
- data/doc/MarilynRPC/ServiceCache.html +481 -0
- data/doc/MarilynRPC.html +108 -0
- data/doc/_index.html +219 -0
- data/doc/class_list.html +36 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +53 -0
- data/doc/css/style.css +318 -0
- data/doc/file.README.html +154 -0
- data/doc/file_list.html +38 -0
- data/doc/frames.html +13 -0
- data/doc/index.html +154 -0
- data/doc/js/app.js +203 -0
- data/doc/js/full_list.js +149 -0
- data/doc/js/jquery.js +16 -0
- data/doc/method_list.html +467 -0
- data/doc/top-level-namespace.html +88 -0
- data/examples/async/client.rb +40 -0
- data/examples/async/server.rb +26 -0
- data/examples/callbacks/client.rb +8 -0
- data/examples/callbacks/server.rb +26 -0
- data/examples/secure/client.rb +9 -0
- data/examples/secure/server.rb +22 -0
- data/kiss.png +0 -0
- data/lib/marilyn-rpc/client.rb +91 -26
- data/lib/marilyn-rpc/gentleman.rb +4 -1
- data/lib/marilyn-rpc/mails.rb +1 -1
- data/lib/marilyn-rpc/server.rb +27 -3
- data/lib/marilyn-rpc/service.rb +64 -0
- data/lib/marilyn-rpc/service_cache.rb +13 -2
- data/lib/marilyn-rpc/version.rb +1 -1
- metadata +39 -3
data/LICENCE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2011 Vincent Landgraf
|
2
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
3
|
+
this software and associated documentation files (the "Software"), to deal in
|
4
|
+
the Software without restriction, including without limitation the rights to
|
5
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
6
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
7
|
+
subject to the following conditions:
|
8
|
+
|
9
|
+
The above copyright notice and this permission notice shall be included in all
|
10
|
+
copies or substantial portions of the Software.
|
11
|
+
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
13
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
14
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
15
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
16
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
17
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
18
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
![alt text](https://raw.github.com/threez/marilyn-rpc/master/kiss.png "MarilynRPC")
|
2
|
+
|
3
|
+
# MarilynRPC
|
4
|
+
|
5
|
+
Marilyn is a simple, elegant rpc service and client infrastructure that has
|
6
|
+
learned some lessons on how we organize our code in typical web projects like
|
7
|
+
rails. It's purpose is to call multiple services over a persistent connection.
|
8
|
+
The services are unique per connection, so if you have 50 connections, 50
|
9
|
+
service objects will be used, if (and only if) they are requested by the client.
|
10
|
+
|
11
|
+
Since this is a session dedicated to one connection, marilyn has support for per
|
12
|
+
connection caching by using instance variables. Further on, it is planned to
|
13
|
+
enhance the capabilities of marilyn to allow connection based authentication.
|
14
|
+
Like in other protocols (e.g. IMAP) where some methods can be called
|
15
|
+
unauthenticated and some not.
|
16
|
+
|
17
|
+
Like in IMAP marilyn supports sending of multiple requests to a server over one
|
18
|
+
connection. This feature is called multiplexing supported by the current
|
19
|
+
`NativeClient` implementation.
|
20
|
+
|
21
|
+
The services rely on the eventmachine reactor. Marilyn supports asynchronous
|
22
|
+
responses based on the so called `Gentleman`. This class is a proxy object that
|
23
|
+
will handle the async responses for you.
|
24
|
+
|
25
|
+
Due to it's internals marilyn is very fast. On my local machine i can achieve
|
26
|
+
about 5000 (req + resp)/s.
|
27
|
+
|
28
|
+
Serialization of all data is done using ruby's build in `Marshal#dump` and `#load`. Since it was the fastest solution i found for typical scenarios.
|
29
|
+
|
30
|
+
It is especially designed for local connections too and therefore build to run
|
31
|
+
on both tcp and unix domain socket connections. Due to it's implementation in
|
32
|
+
operation systems is a unix domain socket typically faster than a tcp localhost
|
33
|
+
connection. I my tests up to 30 percent faster.
|
34
|
+
|
35
|
+
## Install
|
36
|
+
|
37
|
+
Easy and common using gems:
|
38
|
+
|
39
|
+
gem install marilynrpc
|
40
|
+
|
41
|
+
## Server Example
|
42
|
+
|
43
|
+
This is a sample server that exposes 2 Services that can be easily exposed using
|
44
|
+
the eventmachine `start_server` function:
|
45
|
+
|
46
|
+
require "marilyn-rpc"
|
47
|
+
require "eventmachine"
|
48
|
+
|
49
|
+
class CalcService < MarilynRPC::Service
|
50
|
+
register :calc
|
51
|
+
|
52
|
+
def add(a, b)
|
53
|
+
a + b
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class TimeService < MarilynRPC::Service
|
58
|
+
register :time
|
59
|
+
|
60
|
+
def current
|
61
|
+
Time.now
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
EM.run {
|
66
|
+
EM.start_server "localhost", 8483, MarilynRPC::Server
|
67
|
+
}
|
68
|
+
|
69
|
+
## NativeClient Example (pure ruby)
|
70
|
+
|
71
|
+
The native client is a pure ruby implementation and dosn't require eventmachine
|
72
|
+
at all. Therefor it is very easy to use. However the downside is, that the
|
73
|
+
client is blocking for the call. But, since marilyn calls last only for
|
74
|
+
fractions of a millisecond (on a local connection) there should be no problem in
|
75
|
+
typical setups.
|
76
|
+
|
77
|
+
require "marilyn-rpc"
|
78
|
+
|
79
|
+
client = MarilynRPC::NativeClient.connect_tcp('localhost', 8483)
|
80
|
+
CalcService = client.for(:calc)
|
81
|
+
TimeService = client.for(:time)
|
82
|
+
|
83
|
+
p CalcService.add(1, 2)
|
84
|
+
p TimeService.current
|
85
|
+
|
86
|
+
client.disconnect
|
87
|
+
|
88
|
+
## Service Events
|
89
|
+
|
90
|
+
Because a client has a dedicated service it is possible to add connect and
|
91
|
+
disconnect callbacks. These callbacks may help your application to
|
92
|
+
request/cache/optimize certain aspects of your service. Here is an example:
|
93
|
+
|
94
|
+
class EventsService < MarilynRPC::Service
|
95
|
+
register :events
|
96
|
+
after_connect :connected
|
97
|
+
after_disconnect :disconnected
|
98
|
+
|
99
|
+
def connected
|
100
|
+
puts "client connected"
|
101
|
+
end
|
102
|
+
|
103
|
+
def notify(msg)
|
104
|
+
puts msg
|
105
|
+
end
|
106
|
+
|
107
|
+
def disconnected
|
108
|
+
puts "client disconnected"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
## Security
|
113
|
+
|
114
|
+
If you are using a tcp connection you can secure the connection using tls/ssl.
|
115
|
+
To enable it on the server side one has to pass the secure flag:
|
116
|
+
|
117
|
+
EM.run {
|
118
|
+
EM.start_server("localhost", 8008, MarilynRPC::Server, :secure => true)
|
119
|
+
}
|
120
|
+
|
121
|
+
The client also simply has to enable a secure connection:
|
122
|
+
|
123
|
+
client = MarilynRPC::NativeClient.connect_tcp('localhost', 8008, :secure => true)
|
124
|
+
|
125
|
+
## Async Server Example & NativeClient
|
126
|
+
|
127
|
+
As previously said, the server can use the `Gentleman` to issue asynchronous
|
128
|
+
responses:
|
129
|
+
|
130
|
+
class SimpleCommandService < MarilynRPC::Service
|
131
|
+
register :cmd
|
132
|
+
|
133
|
+
def exec(line)
|
134
|
+
MarilynRPC::Gentleman.proxy do |helper|
|
135
|
+
EM.system(line, &helper)
|
136
|
+
|
137
|
+
lambda do |output,status|
|
138
|
+
if (code = status.exitstatus) == 0
|
139
|
+
output
|
140
|
+
else
|
141
|
+
code
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
The asynchronous server is transparent to the client. The client, doen't even
|
149
|
+
know, that his request is processed asynchronously. If the client make use of
|
150
|
+
the multiplexing feature he can use multiple threads to do so:
|
151
|
+
|
152
|
+
client = MarilynRPC::NativeClient.connect_tcp('localhost', 8000)
|
153
|
+
SimpleCommandService = client.for(:cmd)
|
154
|
+
|
155
|
+
start_time = Time.now
|
156
|
+
|
157
|
+
Thread.new do
|
158
|
+
SimpleCommandService.exec("sleep 5")
|
159
|
+
puts "=== ls -al\n: " + SimpleCommandService.exec("ls -al")
|
160
|
+
end
|
161
|
+
|
162
|
+
Thread.new do
|
163
|
+
SimpleCommandService.exec("sleep 2")
|
164
|
+
puts "=== uname -a\n: " + SimpleCommandService.exec("uname -a")
|
165
|
+
end
|
166
|
+
|
167
|
+
## License / Author
|
168
|
+
|
169
|
+
Copyright (c) 2011 Vincent Landgraf
|
170
|
+
All Rights Reserved. Released under a [MIT License](LICENCE).
|