Commit | Line | Data |
9e72f0cf |
1 | package Object::Remote; |
2 | |
3 | use Object::Remote::MiniLoop; |
676438a1 |
4 | use Object::Remote::Handle; |
4a9fa1a5 |
5 | use Object::Remote::Logging qw( :log ); |
e144d525 |
6 | use Module::Runtime qw(use_module); |
9e72f0cf |
7 | |
b7bac4e2 |
8 | our $VERSION = '0.004000'; # 0.4.0 |
52ea6942 |
9 | |
84b04178 |
10 | sub new::on { |
11 | my ($class, $on, @args) = @_; |
4c17fea5 |
12 | my $conn = __PACKAGE__->connect($on); |
5d59cb98 |
13 | log_trace { sprintf("constructing instance of $class on connection for child pid of %i", $conn->child_pid) }; |
11dbd4a0 |
14 | return $conn->remote_object(class => $class, args => \@args); |
84b04178 |
15 | } |
16 | |
624b459b |
17 | sub can::on { |
18 | my ($class, $on, $name) = @_; |
19 | my $conn = __PACKAGE__->connect($on); |
5d59cb98 |
20 | log_trace { "Invoking remote \$class->can('$name')" }; |
624b459b |
21 | return $conn->remote_sub(join('::', $class, $name)); |
22 | } |
23 | |
676438a1 |
24 | sub new { |
25 | shift; |
26 | Object::Remote::Handle->new(@_)->proxy; |
9e72f0cf |
27 | } |
28 | |
4c17fea5 |
29 | sub connect { |
71087610 |
30 | my ($class, $to, @args) = @_; |
31 | use_module('Object::Remote::Connection')->maybe::start::new_from_spec($to, @args); |
4c17fea5 |
32 | } |
33 | |
9e72f0cf |
34 | sub current_loop { |
35 | our $Current_Loop ||= Object::Remote::MiniLoop->new |
36 | } |
37 | |
9e72f0cf |
38 | 1; |
b9a9982d |
39 | |
40 | =head1 NAME |
41 | |
42 | Object::Remote - Call methods on objects in other processes or on other hosts |
43 | |
44 | =head1 SYNOPSIS |
45 | |
46 | Creating a connection: |
47 | |
48 | use Object::Remote; |
49 | |
50 | my $conn = Object::Remote->connect('myserver'); # invokes ssh |
51 | |
52 | Calling a subroutine: |
53 | |
54 | my $capture = IPC::System::Simple->can::on($conn, 'capture'); |
55 | |
56 | warn $capture->('uptime'); |
57 | |
58 | Using an object: |
59 | |
60 | my $eval = Eval::WithLexicals->new::on($conn); |
61 | |
62 | $eval->eval(q{my $x = `uptime`}); |
63 | |
64 | warn $eval->eval(q{$x}); |
65 | |
66 | Importantly: 'myserver' only requires perl 5.8+ - no non-core modules need to |
67 | be installed on the far side, Object::Remote takes care of it for you! |
68 | |
69 | =head1 DESCRIPTION |
70 | |
71 | Object::Remote allows you to create an object in another process - usually |
72 | one running on another machine you can connect to via ssh, although there |
73 | are other connection mechanisms available. |
74 | |
75 | The idea here is that in many cases one wants to be able to run a piece of |
76 | code on another machine, or perhaps many other machines - but without having |
77 | to install anything on the far side. |
78 | |
79 | =head1 COMPONENTS |
80 | |
81 | =head2 Object::Remote |
82 | |
83 | The "main" API, which provides the L</connect> method to create a connection |
84 | to a remote process/host, L</new::on> to create an object on a connection, |
85 | and L</can::on> to retrieve a subref over a connection. |
86 | |
87 | =head2 Object::Remote::Connection |
88 | |
89 | The object representing a connection, which provides the |
90 | L<Object::Remote::Connection/remote_object> and |
91 | L<Object::Remote::Connection/remote_sub> methods that are used by |
92 | L</new::on> and L</can::on> to return proxies for objects and subroutines |
93 | on the far side. |
94 | |
95 | =head2 Object::Remote::Future |
96 | |
97 | Code for dealing with asynchronous operations, which provides the |
98 | L<Object::Remote::Future/start::method> syntax for calling a possibly |
99 | asynchronous method without blocking, and |
100 | L<Object::Remote::Future/await_future> and L<Object::Remote::Future/await_all> |
101 | to block until an asynchronous call completes or fails. |
102 | |
103 | =head1 METHODS |
104 | |
105 | =head2 connect |
106 | |
107 | my $conn = Object::Remote->connect('-'); # fork()ed connection |
108 | |
109 | my $conn = Object::Remote->connect('myserver'); # connection over ssh |
110 | |
111 | my $conn = Object::Remote->connect('user@myserver'); # connection over ssh |
112 | |
113 | my $conn = Object::Remote->connect('root@'); # connection over sudo |
114 | |
4e25b1fd |
115 | my $conn = Object::Remote->connect('root@', %args); # can take optional args |
116 | |
117 | Convenience method for calling L<Object::Remote::Connection/new_from_spec> in a |
118 | L<Future>-compatible way. |
119 | |
b9a9982d |
120 | =head2 new::on |
121 | |
122 | my $eval = Eval::WithLexicals->new::on($conn); |
123 | |
124 | my $eval = Eval::WithLexicals->new::on('myserver'); # implicit connect |
125 | |
126 | my $obj = Some::Class->new::on($conn, %args); # with constructor arguments |
127 | |
128 | =head2 can::on |
129 | |
130 | my $hostname = Sys::Hostname->can::on($conn, 'hostname'); |
131 | |
132 | my $hostname = Sys::Hostname->can::on('myserver', 'hostname'); |
133 | |
d672a9bf |
134 | =head1 ENVIRONMENT |
135 | |
136 | =over 4 |
137 | |
138 | =item OBJECT_REMOTE_PERL_BIN |
139 | |
140 | When starting a new Perl interpreter the contents of this environment |
141 | variable will be used as the path to the executable. If the variable |
142 | is not set the path is 'perl' |
143 | |
144 | =item OBJECT_REMOTE_LOG_LEVEL |
145 | |
146 | Setting this environment variable will enable logging and send all log messages |
147 | at the specfied level or higher to STDERR. Valid level names are: trace debug |
148 | verbose info warn error fatal |
149 | |
150 | =item OBJECT_REMOTE_LOG_FORMAT |
151 | |
152 | The format of the logging output is configurable. By setting this environment variable |
153 | the format can be controlled via printf style position variables. See |
154 | L<Object::Remote::Logging::Logger>. |
155 | |
156 | =item OBJECT_REMOTE_LOG_FORWARDING |
157 | |
b0ec7e3b |
158 | Forward log events from remote connections to the local Perl interpreter. Set to 1 to enable |
159 | this feature which is disabled by default. See L<Object::Remote::Logging>. |
d672a9bf |
160 | |
161 | =item OBJECT_REMOTE_LOG_SELECTIONS |
162 | |
163 | Space seperated list of class names to display logs for if logging output is enabled. Default |
164 | value is "Object::Remote::Logging" which selects all logs generated by Object::Remote. |
2d3c094d |
165 | See L<Object::Remote::Logging>. |
d672a9bf |
166 | |
167 | =back |
168 | |
b0ec7e3b |
169 | =head1 KNOWN ISSUES |
170 | |
55c0d020 |
171 | =over 4 |
b0ec7e3b |
172 | |
173 | =item Large data structures |
174 | |
175 | Object::Remote communication is encapsalated with JSON and values passed to remote objects |
176 | will be serialized with it. When sending large data structures or data structures with a lot |
177 | of deep complexity (hashes in arrays in hashes in arrays) the processor time and memory requirements |
178 | for serialization and deserialization can be either painful or unworkable. During times of |
179 | serialization the local or remote nodes will be blocked potentially causing all remote |
180 | interpreters to block as well under worse case conditions. |
181 | |
de9062cf |
182 | To help deal with this issue it is possible to configure resource ulimits for a Perl interpreter |
183 | that is executed by Object::Remote. See C<Object::Remote::Role::Connector::PerlInterpreter> |
184 | for details on the perl_command attribute. |
b0ec7e3b |
185 | |
186 | =item User can starve run loop of execution opportunities |
187 | |
188 | The Object::Remote run loop is responsible for performing I/O and managing timers in a cooperative |
189 | multitasing way but it can only do these tasks when the user has given control to Object::Remote. |
190 | There are times when Object::Remote must wait for the user to return control to the run loop and |
191 | during these times no I/O can be performed and no timers can be executed. |
192 | |
193 | As an end user of Object::Remote if you depend on connection timeouts, the watch dog or timely |
194 | results from remote objects then be sure to hand control back to Object::Remote as soon as you |
195 | can. |
196 | |
197 | =item Run loop favors certain filehandles/connections |
198 | |
199 | =item High levels of load can starve timers of execution opportunities |
200 | |
201 | These are issues that only become a problem at large scales. The end result of these two |
202 | issues is quite similiar: some remote objects may block while the local run loop is either busy |
203 | servicing a different connection or is not executing because control has not yet been returned to |
204 | it. For the same reasons timers may not get an opportunity to execute in a timely way. |
205 | |
206 | Internally Object::Remote uses timers managed by the run loop for control tasks. Under |
207 | high load the timers can be preempted by servicing I/O on the filehandles and execution |
208 | can be severely delayed. This can lead to connection watchdogs not being updated or connection |
209 | timeouts taking longer than configured. |
210 | |
211 | =item Deadlocks |
212 | |
55c0d020 |
213 | Deadlocks can happen quite easily because of flaws in programs that use Object::Remote or |
b0ec7e3b |
214 | Object::Remote itself so the C<Object::Remote::WatchDog> is available. When used the run |
215 | loop will periodically update the watch dog object on the remote Perl interpreter. If the |
216 | watch dog goes longer than the configured interval with out being updated then it will |
217 | terminate the Perl process. The watch dog will terminate the process even if a deadlock |
218 | condition has occured. |
219 | |
220 | =item Log forwarding at scale can starve timers of execution opportunities |
221 | |
222 | Currently log forwarding can be problematic at large scales. When there is a large |
223 | amount of log events the load produced by log forwarding can be high enough that it starves |
224 | the timers and the remote object watch dogs (if in use) don't get updated in timely way |
225 | causing them to erroneously terminate the Perl process. If the watch dog is not in use |
226 | then connection timeouts can be delayed but will execute when load settles down enough. |
227 | |
228 | Because of the load related issues Object::Remote disables log forwarding by default. |
229 | See C<Object::Remote::Logging> for information on log forwarding. |
230 | |
231 | =back |
232 | |
b9a9982d |
233 | =head1 SUPPORT |
234 | |
235 | IRC: #web-simple on irc.perl.org |
236 | |
237 | =head1 AUTHOR |
238 | |
239 | mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk> |
240 | |
241 | =head1 CONTRIBUTORS |
242 | |
255f68c5 |
243 | bfwg - Colin Newell (cpan:NEWELLC) <colin.newell@gmail.com> |
244 | |
b9a9982d |
245 | phaylon - Robert Sedlacek (cpan:PHAYLON) <r.sedlacek@shadowcat.co.uk> |
246 | |
d672a9bf |
247 | triddle - Tyler Riddle (cpan:TRIDDLE) <t.riddle@shadowcat.co.uk> |
248 | |
b9a9982d |
249 | =head1 SPONSORS |
250 | |
251 | Parts of this code were paid for by |
252 | |
253 | Socialflow L<http://www.socialflow.com> |
254 | |
255 | Shadowcat Systems L<http://www.shadow.cat> |
256 | |
257 | =head1 COPYRIGHT |
258 | |
259 | Copyright (c) 2012 the Object::Remote L</AUTHOR>, L</CONTRIBUTORS> and |
260 | L</SPONSORS> as listed above. |
261 | |
262 | =head1 LICENSE |
263 | |
264 | This library is free software and may be distributed under the same terms |
265 | as perl itself. |
266 | |
267 | =cut |