marilyn-rpc 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/benchmark/client.rb +42 -14
  2. data/doc/MarilynRPC.html +108 -0
  3. data/doc/MarilynRPC/CallRequestMail.html +578 -0
  4. data/doc/MarilynRPC/CallResponseMail.html +418 -0
  5. data/doc/MarilynRPC/Envelope.html +705 -0
  6. data/doc/MarilynRPC/ExceptionMail.html +338 -0
  7. data/doc/MarilynRPC/Gentleman.html +658 -0
  8. data/doc/MarilynRPC/MailFactory.html +284 -0
  9. data/doc/MarilynRPC/MailHelper.html +489 -0
  10. data/doc/MarilynRPC/NativeClient.html +579 -0
  11. data/doc/MarilynRPC/NativeClientProxy.html +303 -0
  12. data/doc/MarilynRPC/Server.html +406 -0
  13. data/doc/MarilynRPC/Service.html +599 -0
  14. data/doc/MarilynRPC/ServiceCache.html +481 -0
  15. data/doc/_index.html +219 -0
  16. data/doc/class_list.html +36 -0
  17. data/doc/css/common.css +1 -0
  18. data/doc/css/full_list.css +53 -0
  19. data/doc/css/style.css +318 -0
  20. data/doc/file.README.html +154 -0
  21. data/doc/file_list.html +38 -0
  22. data/doc/frames.html +13 -0
  23. data/doc/index.html +154 -0
  24. data/doc/js/app.js +203 -0
  25. data/doc/js/full_list.js +149 -0
  26. data/doc/js/jquery.js +16 -0
  27. data/doc/method_list.html +467 -0
  28. data/doc/top-level-namespace.html +88 -0
  29. data/lib/marilyn-rpc/client.rb +20 -21
  30. data/lib/marilyn-rpc/envelope.rb +27 -10
  31. data/lib/marilyn-rpc/gentleman.rb +8 -1
  32. data/lib/marilyn-rpc/mails.rb +40 -55
  33. data/lib/marilyn-rpc/server.rb +4 -11
  34. data/lib/marilyn-rpc/service.rb +1 -1
  35. data/lib/marilyn-rpc/service_cache.rb +7 -4
  36. data/lib/marilyn-rpc/version.rb +1 -1
  37. data/marilyn-rpc-0.0.2.gem +0 -0
  38. data/spec/envelope_spec.rb +18 -9
  39. data/spec/gentleman_spec.rb +14 -3
  40. data/spec/mails_spec.rb +2 -1
  41. data/spec/server_spec.rb +4 -4
  42. data/spec/service_cache_spec.rb +8 -0
  43. data/spec/spec_helper.rb +9 -2
  44. metadata +30 -22
@@ -0,0 +1,154 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>MarilynRPC Documentation</title>
7
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
8
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
9
+
10
+ <script type="text/javascript" charset="utf-8">
11
+ relpath = '';
12
+ if (relpath != '') relpath += '/';
13
+ </script>
14
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
15
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
16
+
17
+ </head>
18
+ <body>
19
+ <script type="text/javascript" charset="utf-8">
20
+ if (window.top.frames.main) document.body.className = 'frames';
21
+ </script>
22
+
23
+ <div id="header">
24
+ <div id="menu">
25
+
26
+ <a href="_index.html" title="Index">Index</a> &raquo;
27
+ <span class="title">File: README</span>
28
+
29
+
30
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
31
+ </div>
32
+
33
+ <div id="search">
34
+ <a id="class_list_link" href="#">Class List</a>
35
+ <a id="method_list_link" href="#">Method List</a>
36
+ <a id ="file_list_link" href="#">File List</a>
37
+ </div>
38
+
39
+ <div class="clear"></div>
40
+ </div>
41
+
42
+ <iframe id="search_frame"></iframe>
43
+
44
+ <div id="content"><div id='filecontents'><p><img src='https://raw.github.com/threez/marilyn-rpc/master/kiss.png' alt='alt text' /></p>
45
+
46
+ <h1 id='marilynrpc'>MarilynRPC</h1>
47
+
48
+ <p>Marilyn is a simple, elegant rpc service and client infrastructure that has learned some lessons on how we organize our code in typical web projects like rails. It&#8217;s purpose is to call multiple services over a persistent connection. The services are unique per connection, so if you have 50 connections, 50 service objects will be used, if (and only if) they are requested by the client.</p>
49
+
50
+ <p>Since this is a session dedicated to one connection, marilyn has support for per connection caching by using instance variables. Further on, it is planned to enhance the capabilities of marilyn to allow connection based authentication. Like in other protocols (e.g. IMAP) where come method can be called unauthenticated and some not. We plan to enable TLS to have a secure connection. Like in IMAP marilyn supports sending of multiple requests to a server over one connection. This feature is not supported by the current client implementation, but things will get changed in the feature.</p>
51
+
52
+ <p>The services rely on the eventmachine reactor. Marilyn supports asynchronous responses based on the so called <code>Gentleman</code>. This class is a proxy object that will handle the async responses for you.</p>
53
+
54
+ <p>Due to it&#8217;s internals marilyn is very fast. On my local machine i can achieve about 5000 (req + resp)/s.</p>
55
+
56
+ <p>Serialization of all data is done using ruby&#8217;s build in <code>Marshal#dump</code> and <code>#load</code>. Since it was the fastest solution i found for typical scenarios.</p>
57
+
58
+ <p>It is especially designed for local connections too and therefore build to run on both tcp and unix domain socket connections. Due to it&#8217;s implementation in operation systems is a unix domain socket typically faster than a tcp localhost connection. I my tests up to 30 percent faster.</p>
59
+
60
+ <h2 id='install'>Install</h2>
61
+
62
+ <p>Easy and common using gems:</p>
63
+
64
+ <pre class="code"><span class='gem identifier id'>gem</span> <span class='install identifier id'>install</span> <span class='marilynrpc identifier id'>marilynrpc</span>
65
+ </pre>
66
+
67
+ <h2 id='server_example'>Server Example</h2>
68
+
69
+ <p>This is a sample server that exposes 2 Services that can be easily exposed using the eventmachine <code>start_server</code> function:</p>
70
+
71
+ <pre class="code"><span class='require identifier id'>require</span> <span class='string val'>&quot;marilyn-rpc&quot;</span>
72
+ <span class='require identifier id'>require</span> <span class='string val'>&quot;eventmachine&quot;</span>
73
+
74
+ <span class='class class kw'>class</span> <span class='CalcService constant id'>CalcService</span> <span class='lt op'>&lt;</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Service constant id'>Service</span>
75
+ <span class='register identifier id'>register</span> <span class='symbol val'>:calc</span>
76
+
77
+ <span class='def def kw'>def</span> <span class='add identifier id'>add</span><span class='lparen token'>(</span><span class='a identifier id'>a</span><span class='comma token'>,</span> <span class='b identifier id'>b</span><span class='rparen token'>)</span>
78
+ <span class='a identifier id'>a</span> <span class='plus op'>+</span> <span class='b identifier id'>b</span>
79
+ <span class='end end kw'>end</span>
80
+ <span class='end end kw'>end</span>
81
+
82
+ <span class='class class kw'>class</span> <span class='TimeService constant id'>TimeService</span> <span class='lt op'>&lt;</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Service constant id'>Service</span>
83
+ <span class='register identifier id'>register</span> <span class='symbol val'>:time</span>
84
+
85
+ <span class='def def kw'>def</span> <span class='current identifier id'>current</span>
86
+ <span class='Time constant id'>Time</span><span class='dot token'>.</span><span class='now identifier id'>now</span>
87
+ <span class='end end kw'>end</span>
88
+ <span class='end end kw'>end</span>
89
+
90
+ <span class='EM constant id'>EM</span><span class='dot token'>.</span><span class='run identifier id'>run</span> <span class='lbrace token'>{</span>
91
+ <span class='EM constant id'>EM</span><span class='dot token'>.</span><span class='start_server identifier id'>start_server</span> <span class='string val'>&quot;localhost&quot;</span><span class='comma token'>,</span> <span class='integer val'>8483</span><span class='comma token'>,</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Server constant id'>Server</span>
92
+ <span class='rbrace token'>}</span>
93
+ </pre>
94
+
95
+ <h2 id='nativeclient_example_pure_ruby'>NativeClient Example (pure ruby)</h2>
96
+
97
+ <p>The native client is a pure ruby implementation and dosn&#8217;t require eventmachine at all. Therefor it is very easy to use. However the downside is, that the client is blocking for the call. But, since marilyn calls last only for fractions of a millisecond (on a local connection) there should be no problem in typical setups.</p>
98
+
99
+ <pre class="code"><span class='require identifier id'>require</span> <span class='string val'>&quot;marilyn-rpc&quot;</span>
100
+
101
+ <span class='client identifier id'>client</span> <span class='assign token'>=</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='NativeClient constant id'>NativeClient</span><span class='dot token'>.</span><span class='connect_tcp identifier id'>connect_tcp</span><span class='lparen token'>(</span><span class='string val'>'localhost'</span><span class='comma token'>,</span> <span class='integer val'>8483</span><span class='rparen token'>)</span>
102
+ <span class='CalcService constant id'>CalcService</span> <span class='assign token'>=</span> <span class='client identifier id'>client</span><span class='dot token'>.</span><span class='for identifier id'>for</span><span class='lparen token'>(</span><span class='symbol val'>:calc</span><span class='rparen token'>)</span>
103
+ <span class='TimeService constant id'>TimeService</span> <span class='assign token'>=</span> <span class='client identifier id'>client</span><span class='dot token'>.</span><span class='for identifier id'>for</span><span class='lparen token'>(</span><span class='symbol val'>:time</span><span class='rparen token'>)</span>
104
+
105
+ <span class='p identifier id'>p</span> <span class='CalcService constant id'>CalcService</span><span class='dot token'>.</span><span class='add identifier id'>add</span><span class='lparen token'>(</span><span class='integer val'>1</span><span class='comma token'>,</span> <span class='integer val'>2</span><span class='rparen token'>)</span>
106
+ <span class='p identifier id'>p</span> <span class='TimeService constant id'>TimeService</span><span class='dot token'>.</span><span class='current identifier id'>current</span>
107
+
108
+ <span class='client identifier id'>client</span><span class='dot token'>.</span><span class='disconnect identifier id'>disconnect</span>
109
+ </pre>
110
+
111
+ <h2 id='service_events'>Service Events</h2>
112
+
113
+ <p>Because a client has a dedicated service it is possible to add connect and disconnect callbacks. These callbacks may help your application to request/cache/optimize certain aspects of your service. Here is an example:</p>
114
+
115
+ <pre class="code"><span class='class class kw'>class</span> <span class='EventsService constant id'>EventsService</span> <span class='lt op'>&lt;</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Service constant id'>Service</span>
116
+ <span class='register identifier id'>register</span> <span class='symbol val'>:events</span>
117
+ <span class='after_connect identifier id'>after_connect</span> <span class='symbol val'>:connected</span>
118
+ <span class='after_disconnect identifier id'>after_disconnect</span> <span class='symbol val'>:disconnected</span>
119
+
120
+ <span class='def def kw'>def</span> <span class='connected identifier id'>connected</span>
121
+ <span class='puts identifier id'>puts</span> <span class='string val'>&quot;client connected&quot;</span>
122
+ <span class='end end kw'>end</span>
123
+
124
+ <span class='def def kw'>def</span> <span class='notify identifier id'>notify</span><span class='lparen token'>(</span><span class='msg identifier id'>msg</span><span class='rparen token'>)</span>
125
+ <span class='puts identifier id'>puts</span> <span class='msg identifier id'>msg</span>
126
+ <span class='end end kw'>end</span>
127
+
128
+ <span class='def def kw'>def</span> <span class='disconnected identifier id'>disconnected</span>
129
+ <span class='puts identifier id'>puts</span> <span class='string val'>&quot;client disconnected&quot;</span>
130
+ <span class='end end kw'>end</span>
131
+ <span class='end end kw'>end</span>
132
+ </pre>
133
+
134
+ <h2 id='async_server_example'>Async Server Example</h2>
135
+
136
+ <p>As previously said, the server can use the <code>Gentleman</code> to issue asynchronous responses:</p>
137
+
138
+ <pre class="code"><span class='TODO constant id'>TODO</span> <span class='dot3 op'>...</span>
139
+ </pre>
140
+
141
+ <p>The asynchronous server is transparent to the client. The client, doen&#8217;t even know, that his request is processed asynchronously.</p>
142
+
143
+ <h2 id='license__author'>License / Author</h2>
144
+
145
+ <p>Copyright (c) 2011 Vincent Landgraf All Rights Reserved. Released under a <a href='LICENCE'>MIT License</a>.</p></div></div>
146
+
147
+ <div id="footer">
148
+ Generated on Wed Jun 8 18:26:44 2011 by
149
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
150
+ 0.6.8 (ruby-1.8.7).
151
+ </div>
152
+
153
+ </body>
154
+ </html>
@@ -0,0 +1,38 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html>
4
+ <head>
5
+ <meta name="Content-Type" content="text/html; charset=utf-8" />
6
+ <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
7
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
8
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
9
+ <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
10
+ <base id="base_target" target="_parent" />
11
+ </head>
12
+ <body>
13
+ <script type="text/javascript" charset="utf-8">
14
+ if (window.top.frames.main) {
15
+ document.getElementById('base_target').target = 'main';
16
+ document.body.className = 'frames';
17
+ }
18
+ </script>
19
+ <div id="content">
20
+ <h1 id="full_list_header">File List</h1>
21
+ <div id="nav">
22
+ <a target="_self" href="class_list.html">Classes</a> |
23
+ <a target="_self" href="method_list.html">Methods</a> |
24
+ <a target="_self" href="file_list.html">Files</a>
25
+ </div>
26
+ <div id="search">Search: <input type="text" /></div>
27
+
28
+ <ul id="full_list" class="files">
29
+
30
+
31
+ <li class="r1"><a href="index.html" title="README">README</a></li>
32
+
33
+
34
+ </ul>
35
+ </div>
36
+ </body>
37
+ </html>
38
+
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
3
+
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+ <title>MarilynRPC Documentation</title>
8
+ </head>
9
+ <frameset cols="20%,*">
10
+ <frame name="list" src="class_list.html" />
11
+ <frame name="main" src="index.html" />
12
+ </frameset>
13
+ </html>
@@ -0,0 +1,154 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>MarilynRPC Documentation</title>
7
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
8
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
9
+
10
+ <script type="text/javascript" charset="utf-8">
11
+ relpath = '';
12
+ if (relpath != '') relpath += '/';
13
+ </script>
14
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
15
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
16
+
17
+ </head>
18
+ <body>
19
+ <script type="text/javascript" charset="utf-8">
20
+ if (window.top.frames.main) document.body.className = 'frames';
21
+ </script>
22
+
23
+ <div id="header">
24
+ <div id="menu">
25
+
26
+ <a href="_index.html" title="Index">Index</a> &raquo;
27
+ <span class="title">File: README</span>
28
+
29
+
30
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
31
+ </div>
32
+
33
+ <div id="search">
34
+ <a id="class_list_link" href="#">Class List</a>
35
+ <a id="method_list_link" href="#">Method List</a>
36
+ <a id ="file_list_link" href="#">File List</a>
37
+ </div>
38
+
39
+ <div class="clear"></div>
40
+ </div>
41
+
42
+ <iframe id="search_frame"></iframe>
43
+
44
+ <div id="content"><div id='filecontents'><p><img src='https://raw.github.com/threez/marilyn-rpc/master/kiss.png' alt='alt text' /></p>
45
+
46
+ <h1 id='marilynrpc'>MarilynRPC</h1>
47
+
48
+ <p>Marilyn is a simple, elegant rpc service and client infrastructure that has learned some lessons on how we organize our code in typical web projects like rails. It&#8217;s purpose is to call multiple services over a persistent connection. The services are unique per connection, so if you have 50 connections, 50 service objects will be used, if (and only if) they are requested by the client.</p>
49
+
50
+ <p>Since this is a session dedicated to one connection, marilyn has support for per connection caching by using instance variables. Further on, it is planned to enhance the capabilities of marilyn to allow connection based authentication. Like in other protocols (e.g. IMAP) where come method can be called unauthenticated and some not. We plan to enable TLS to have a secure connection. Like in IMAP marilyn supports sending of multiple requests to a server over one connection. This feature is not supported by the current client implementation, but things will get changed in the feature.</p>
51
+
52
+ <p>The services rely on the eventmachine reactor. Marilyn supports asynchronous responses based on the so called <code>Gentleman</code>. This class is a proxy object that will handle the async responses for you.</p>
53
+
54
+ <p>Due to it&#8217;s internals marilyn is very fast. On my local machine i can achieve about 5000 (req + resp)/s.</p>
55
+
56
+ <p>Serialization of all data is done using ruby&#8217;s build in <code>Marshal#dump</code> and <code>#load</code>. Since it was the fastest solution i found for typical scenarios.</p>
57
+
58
+ <p>It is especially designed for local connections too and therefore build to run on both tcp and unix domain socket connections. Due to it&#8217;s implementation in operation systems is a unix domain socket typically faster than a tcp localhost connection. I my tests up to 30 percent faster.</p>
59
+
60
+ <h2 id='install'>Install</h2>
61
+
62
+ <p>Easy and common using gems:</p>
63
+
64
+ <pre class="code"><span class='gem identifier id'>gem</span> <span class='install identifier id'>install</span> <span class='marilynrpc identifier id'>marilynrpc</span>
65
+ </pre>
66
+
67
+ <h2 id='server_example'>Server Example</h2>
68
+
69
+ <p>This is a sample server that exposes 2 Services that can be easily exposed using the eventmachine <code>start_server</code> function:</p>
70
+
71
+ <pre class="code"><span class='require identifier id'>require</span> <span class='string val'>&quot;marilyn-rpc&quot;</span>
72
+ <span class='require identifier id'>require</span> <span class='string val'>&quot;eventmachine&quot;</span>
73
+
74
+ <span class='class class kw'>class</span> <span class='CalcService constant id'>CalcService</span> <span class='lt op'>&lt;</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Service constant id'>Service</span>
75
+ <span class='register identifier id'>register</span> <span class='symbol val'>:calc</span>
76
+
77
+ <span class='def def kw'>def</span> <span class='add identifier id'>add</span><span class='lparen token'>(</span><span class='a identifier id'>a</span><span class='comma token'>,</span> <span class='b identifier id'>b</span><span class='rparen token'>)</span>
78
+ <span class='a identifier id'>a</span> <span class='plus op'>+</span> <span class='b identifier id'>b</span>
79
+ <span class='end end kw'>end</span>
80
+ <span class='end end kw'>end</span>
81
+
82
+ <span class='class class kw'>class</span> <span class='TimeService constant id'>TimeService</span> <span class='lt op'>&lt;</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Service constant id'>Service</span>
83
+ <span class='register identifier id'>register</span> <span class='symbol val'>:time</span>
84
+
85
+ <span class='def def kw'>def</span> <span class='current identifier id'>current</span>
86
+ <span class='Time constant id'>Time</span><span class='dot token'>.</span><span class='now identifier id'>now</span>
87
+ <span class='end end kw'>end</span>
88
+ <span class='end end kw'>end</span>
89
+
90
+ <span class='EM constant id'>EM</span><span class='dot token'>.</span><span class='run identifier id'>run</span> <span class='lbrace token'>{</span>
91
+ <span class='EM constant id'>EM</span><span class='dot token'>.</span><span class='start_server identifier id'>start_server</span> <span class='string val'>&quot;localhost&quot;</span><span class='comma token'>,</span> <span class='integer val'>8483</span><span class='comma token'>,</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Server constant id'>Server</span>
92
+ <span class='rbrace token'>}</span>
93
+ </pre>
94
+
95
+ <h2 id='nativeclient_example_pure_ruby'>NativeClient Example (pure ruby)</h2>
96
+
97
+ <p>The native client is a pure ruby implementation and dosn&#8217;t require eventmachine at all. Therefor it is very easy to use. However the downside is, that the client is blocking for the call. But, since marilyn calls last only for fractions of a millisecond (on a local connection) there should be no problem in typical setups.</p>
98
+
99
+ <pre class="code"><span class='require identifier id'>require</span> <span class='string val'>&quot;marilyn-rpc&quot;</span>
100
+
101
+ <span class='client identifier id'>client</span> <span class='assign token'>=</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='NativeClient constant id'>NativeClient</span><span class='dot token'>.</span><span class='connect_tcp identifier id'>connect_tcp</span><span class='lparen token'>(</span><span class='string val'>'localhost'</span><span class='comma token'>,</span> <span class='integer val'>8483</span><span class='rparen token'>)</span>
102
+ <span class='CalcService constant id'>CalcService</span> <span class='assign token'>=</span> <span class='client identifier id'>client</span><span class='dot token'>.</span><span class='for identifier id'>for</span><span class='lparen token'>(</span><span class='symbol val'>:calc</span><span class='rparen token'>)</span>
103
+ <span class='TimeService constant id'>TimeService</span> <span class='assign token'>=</span> <span class='client identifier id'>client</span><span class='dot token'>.</span><span class='for identifier id'>for</span><span class='lparen token'>(</span><span class='symbol val'>:time</span><span class='rparen token'>)</span>
104
+
105
+ <span class='p identifier id'>p</span> <span class='CalcService constant id'>CalcService</span><span class='dot token'>.</span><span class='add identifier id'>add</span><span class='lparen token'>(</span><span class='integer val'>1</span><span class='comma token'>,</span> <span class='integer val'>2</span><span class='rparen token'>)</span>
106
+ <span class='p identifier id'>p</span> <span class='TimeService constant id'>TimeService</span><span class='dot token'>.</span><span class='current identifier id'>current</span>
107
+
108
+ <span class='client identifier id'>client</span><span class='dot token'>.</span><span class='disconnect identifier id'>disconnect</span>
109
+ </pre>
110
+
111
+ <h2 id='service_events'>Service Events</h2>
112
+
113
+ <p>Because a client has a dedicated service it is possible to add connect and disconnect callbacks. These callbacks may help your application to request/cache/optimize certain aspects of your service. Here is an example:</p>
114
+
115
+ <pre class="code"><span class='class class kw'>class</span> <span class='EventsService constant id'>EventsService</span> <span class='lt op'>&lt;</span> <span class='MarilynRPC constant id'>MarilynRPC</span><span class='colon2 op'>::</span><span class='Service constant id'>Service</span>
116
+ <span class='register identifier id'>register</span> <span class='symbol val'>:events</span>
117
+ <span class='after_connect identifier id'>after_connect</span> <span class='symbol val'>:connected</span>
118
+ <span class='after_disconnect identifier id'>after_disconnect</span> <span class='symbol val'>:disconnected</span>
119
+
120
+ <span class='def def kw'>def</span> <span class='connected identifier id'>connected</span>
121
+ <span class='puts identifier id'>puts</span> <span class='string val'>&quot;client connected&quot;</span>
122
+ <span class='end end kw'>end</span>
123
+
124
+ <span class='def def kw'>def</span> <span class='notify identifier id'>notify</span><span class='lparen token'>(</span><span class='msg identifier id'>msg</span><span class='rparen token'>)</span>
125
+ <span class='puts identifier id'>puts</span> <span class='msg identifier id'>msg</span>
126
+ <span class='end end kw'>end</span>
127
+
128
+ <span class='def def kw'>def</span> <span class='disconnected identifier id'>disconnected</span>
129
+ <span class='puts identifier id'>puts</span> <span class='string val'>&quot;client disconnected&quot;</span>
130
+ <span class='end end kw'>end</span>
131
+ <span class='end end kw'>end</span>
132
+ </pre>
133
+
134
+ <h2 id='async_server_example'>Async Server Example</h2>
135
+
136
+ <p>As previously said, the server can use the <code>Gentleman</code> to issue asynchronous responses:</p>
137
+
138
+ <pre class="code"><span class='TODO constant id'>TODO</span> <span class='dot3 op'>...</span>
139
+ </pre>
140
+
141
+ <p>The asynchronous server is transparent to the client. The client, doen&#8217;t even know, that his request is processed asynchronously.</p>
142
+
143
+ <h2 id='license__author'>License / Author</h2>
144
+
145
+ <p>Copyright (c) 2011 Vincent Landgraf All Rights Reserved. Released under a <a href='LICENCE'>MIT License</a>.</p></div></div>
146
+
147
+ <div id="footer">
148
+ Generated on Wed Jun 8 18:26:44 2011 by
149
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
150
+ 0.6.8 (ruby-1.8.7).
151
+ </div>
152
+
153
+ </body>
154
+ </html>
@@ -0,0 +1,203 @@
1
+ function createSourceLinks() {
2
+ $('.method_details_list .source_code').
3
+ before("<span class='showSource'>[<a href='#' class='toggleSource'>View source</a>]</span>");
4
+ $('.toggleSource').toggle(function() {
5
+ $(this).parent().next().slideDown(100);
6
+ $(this).text("Hide source");
7
+ },
8
+ function() {
9
+ $(this).parent().next().slideUp(100);
10
+ $(this).text("View source");
11
+ });
12
+ }
13
+
14
+ function createDefineLinks() {
15
+ var tHeight = 0;
16
+ $('.defines').after(" <a href='#' class='toggleDefines'>more...</a>");
17
+ $('.toggleDefines').toggle(function() {
18
+ tHeight = $(this).parent().prev().height();
19
+ $(this).prev().show();
20
+ $(this).parent().prev().height($(this).parent().height());
21
+ $(this).text("(less)");
22
+ },
23
+ function() {
24
+ $(this).prev().hide();
25
+ $(this).parent().prev().height(tHeight);
26
+ $(this).text("more...")
27
+ });
28
+ }
29
+
30
+ function createFullTreeLinks() {
31
+ var tHeight = 0;
32
+ $('.inheritanceTree').toggle(function() {
33
+ tHeight = $(this).parent().prev().height();
34
+ $(this).parent().toggleClass('showAll');
35
+ $(this).text("(hide)");
36
+ $(this).parent().prev().height($(this).parent().height());
37
+ },
38
+ function() {
39
+ $(this).parent().toggleClass('showAll');
40
+ $(this).parent().prev().height(tHeight);
41
+ $(this).text("show all")
42
+ });
43
+ }
44
+
45
+ function fixBoxInfoHeights() {
46
+ $('dl.box dd.r1, dl.box dd.r2').each(function() {
47
+ $(this).prev().height($(this).height());
48
+ });
49
+ }
50
+
51
+ function searchFrameLinks() {
52
+ $('#method_list_link').click(function() {
53
+ toggleSearchFrame(this, relpath + 'method_list.html');
54
+ });
55
+
56
+ $('#class_list_link').click(function() {
57
+ toggleSearchFrame(this, relpath + 'class_list.html');
58
+ });
59
+
60
+ $('#file_list_link').click(function() {
61
+ toggleSearchFrame(this, relpath + 'file_list.html');
62
+ });
63
+ }
64
+
65
+ function toggleSearchFrame(id, link) {
66
+ var frame = $('#search_frame');
67
+ $('#search a').removeClass('active').addClass('inactive');
68
+ if (frame.attr('src') == link && frame.css('display') != "none") {
69
+ frame.slideUp(100);
70
+ $('#search a').removeClass('active inactive');
71
+ }
72
+ else {
73
+ $(id).addClass('active').removeClass('inactive');
74
+ frame.attr('src', link).slideDown(100);
75
+ }
76
+ }
77
+
78
+ function linkSummaries() {
79
+ $('.summary_signature').click(function() {
80
+ document.location = $(this).find('a').attr('href');
81
+ });
82
+ }
83
+
84
+ function framesInit() {
85
+ if (window.top.frames.main) {
86
+ document.body.className = 'frames';
87
+ $('#menu .noframes a').attr('href', document.location);
88
+ $('html head title', window.parent.document).text($('html head title').text());
89
+ }
90
+ }
91
+
92
+ function keyboardShortcuts() {
93
+ if (window.top.frames.main) return;
94
+ $(document).keypress(function(evt) {
95
+ if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return;
96
+ if (typeof evt.orignalTarget !== "undefined" &&
97
+ (evt.originalTarget.nodeName == "INPUT" ||
98
+ evt.originalTarget.nodeName == "TEXTAREA")) return;
99
+ switch (evt.charCode) {
100
+ case 67: case 99: $('#class_list_link').click(); break; // 'c'
101
+ case 77: case 109: $('#method_list_link').click(); break; // 'm'
102
+ case 70: case 102: $('#file_list_link').click(); break; // 'f'
103
+ }
104
+ });
105
+ }
106
+
107
+ function summaryToggle() {
108
+ $('.summary_toggle').click(function() {
109
+ localStorage.summaryCollapsed = $(this).text();
110
+ $(this).text($(this).text() == "collapse" ? "expand" : "collapse");
111
+ var next = $(this).parent().parent().next();
112
+ if (next.hasClass('compact')) {
113
+ next.toggle();
114
+ next.next().toggle();
115
+ }
116
+ else if (next.hasClass('summary')) {
117
+ var list = $('<ul class="summary compact" />');
118
+ list.html(next.html());
119
+ list.find('.summary_desc, .note').remove();
120
+ list.find('a').each(function() {
121
+ $(this).html($(this).find('strong').html());
122
+ $(this).parent().html($(this)[0].outerHTML);
123
+ });
124
+ next.before(list);
125
+ next.toggle();
126
+ }
127
+ return false;
128
+ });
129
+ if (localStorage) {
130
+ if (localStorage.summaryCollapsed == "collapse") $('.summary_toggle').click();
131
+ else localStorage.summaryCollapsed = "expand";
132
+ }
133
+ }
134
+
135
+ function fixOutsideWorldLinks() {
136
+ $('a').each(function() {
137
+ if (window.location.host != this.host) this.target = '_parent';
138
+ });
139
+ }
140
+
141
+ function generateTOC() {
142
+ if ($('#filecontents').length == 0) return;
143
+ var _toc = $('<ol class="top"></ol>');
144
+ var show = false;
145
+ var toc = _toc;
146
+ var counter = 0;
147
+ var tags = ['h2', 'h3', 'h4', 'h5', 'h6'];
148
+ if ($('#filecontents h1').length > 1) tags.unshift('h1');
149
+ for (i in tags) { tags[i] = '#filecontents ' + tags[i] }
150
+ var lastTag = parseInt(tags[0][1]);
151
+ $(tags.join(', ')).each(function() {
152
+ if (this.id == "filecontents") return;
153
+ show = true;
154
+ var thisTag = parseInt(this.tagName[1]);
155
+ if (this.id.length == 0) {
156
+ var proposedId = $(this).text().replace(/[^a-z0-9-]/ig, '_');
157
+ if ($('#' + proposedId).length > 0) proposedId += counter++;
158
+ this.id = proposedId;
159
+ }
160
+ if (thisTag > lastTag) {
161
+ for (var i = 0; i < thisTag - lastTag; i++) {
162
+ var tmp = $('<ol/>'); toc.append(tmp); toc = tmp;
163
+ }
164
+ }
165
+ if (thisTag < lastTag) {
166
+ for (var i = 0; i < lastTag - thisTag; i++) toc = toc.parent();
167
+ }
168
+ toc.append('<li><a href="#' + this.id + '">' + $(this).text() + '</a></li>');
169
+ lastTag = thisTag;
170
+ });
171
+ if (!show) return;
172
+ html = '<div id="toc"><p class="title"><a class="hide_toc" href="#"><strong>Table of Contents</strong></a> <small>(<a href="#" class="float_toc">left</a>)</small></p></div>';
173
+ $('#content').prepend(html);
174
+ $('#toc').append(_toc);
175
+ $('#toc .hide_toc').toggle(function() {
176
+ $('#toc .top').slideUp('fast');
177
+ $('#toc').toggleClass('hidden');
178
+ $('#toc .title small').toggle();
179
+ }, function() {
180
+ $('#toc .top').slideDown('fast');
181
+ $('#toc').toggleClass('hidden');
182
+ $('#toc .title small').toggle();
183
+ });
184
+ $('#toc .float_toc').toggle(function() {
185
+ $(this).text('float');
186
+ $('#toc').toggleClass('nofloat');
187
+ }, function() {
188
+ $(this).text('left')
189
+ $('#toc').toggleClass('nofloat');
190
+ });
191
+ }
192
+
193
+ $(framesInit);
194
+ $(createSourceLinks);
195
+ $(createDefineLinks);
196
+ $(createFullTreeLinks);
197
+ $(fixBoxInfoHeights);
198
+ $(searchFrameLinks);
199
+ $(linkSummaries);
200
+ $(keyboardShortcuts);
201
+ $(summaryToggle);
202
+ $(fixOutsideWorldLinks);
203
+ $(generateTOC);