Acme-RPC
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
lib/Acme/RPC.pm view on Meta::CPAN
package Acme::RPC;
Devel::Trace::trace('off') if exists $INC{'Devel/Trace.pm'};
use strict;
use warnings;
our $VERSION = '0.01';
use B;
use B::Deparse;
use Continuity;
use IO::Handle;
# use Devel::Pointer;
use JSON;
use Data::Dumper;
use Devel::Caller 'caller_cv';
use PadWalker 'peek_sub';
use Scalar::Util 'blessed';
my $comment = <<'EOF';
Todo:
* Accept JSON as input too, for the parameters!
* When taking apart CODE, do closes_over() too, not just peek_my().
* Weaken references held in %registry.
* Bug: Second hit with an oid= finds the server not accepting.
* Optionally require a password... use Acme::RPC password => whatever;
* entersubs=1, enterpackages=1, etc args to control how far the recurse goes in building $tree.
* Maybe don't recurse into blessed objects, but dump them nicely upon request.
Or maybe do recurse into them and dump their instance data.
If $oid is passed then recurse into arrays, hashes, and object instance data.
* We don't dump references found inside CODE in the main view.
But if they request a dump for that object, dump it.
Likewise, we're not dumping arrays and hashes, but if they request a dump on it, dump it.
* JSON output on the default tree view too.
We'd have to sanitize our tree...
* Document that people need to use Event::loop or something; an Acme module to insert calls to cede would be awesome for this
* Package names like foo:: should be hyperlinked too; should be able call ?oid=whatever&action=new&args=whatever on them
* The whole tree() recurse thing if it gets any more complicated is going to need a %seen list to avoid infinite recursion.
Think About:
* ?ref is for plain references (array, hash, scalar, code); ?obj is for objects...?
* ?action parameter: dump, call, set, new
new is like call but it accepts a bare package name rather than an oid.
Done:
* The tree structure where each only leafs contain "hits" (references to things that get ?oid links made from them)
is causing confusion and grief.
Need a structure where for any given $node, $node->{chr(0)} is the (possible) object representing that node,
and $node->{everything else} is the stuff under it.
Then given a code ref, $node->{chr(0)} would be the code ref itself, and $node->{everything else} would be lexicals vars.
Given a stash like "foo::", $node->{chr(0)} would actually be \%{'foo::'} and $node->{everything else} would be stuff in that package.
* Rather than only taking oids to dump/call, also take a path in the tree.
* lazy=1 parameter where the last $tree is re-used rather than re-computed.
* Should switch to our own recurse logic from Data::Dumper to support these other things.
* action=dump on anything; in the case of a coderef, find its source on disc or else deparse it
* action=call on coderefs and blessed objects, with an args parameter, or arg1, arg2, arg3, etc, and a method parameter for blessed objs.
* json will croak if a reference contains objects in side it somewhere. Should handle this gracefully.
* Offer JSON output! Not just Data::Dumper. Do this for action=dump, action=call, and the default tree view.
* If Devel::Leak won't give us refs... have to do an Acme::State style crawl from main::,
but crawling into each sub and looking at its lexicals with PadWalker.
Could make for a nice tree view.
Would also make it easy to filter out the variables that hold refs.
* Maybe this should be called Acme::RPC.
* Actually crawl into code refs when recursing the output!
* Devel pointer is too much work also. Maybe we should just cache $tree and then
walk it again when passed an oid. *sigh* Magic isn't working for me today.
Bleah.
EOF
# our $lt;
our $continuity; # don't lose this reference
our @keepalive; # stuff instances of objects created over RPC in there so they don't get garbage collected before the other end can use them
our $tree; # cached tree
our %registry; # oid=>objectrefs
sub import {
Devel::Trace::trace('off') if exists $INC{'Devel/Trace.pm'};
$continuity = Continuity->new(port => 7777, callback => sub {
my $request = shift;
while(1) {
$SIG{PIPE} = 'IGNORE';
my $action = $request->param('action') || 'dump';
my $output = $request->param('output');
my $ob;
$tree = tree('main::') unless $tree and $request->param('lazy');
#
# if they're referencing a specific object, find it
#
if($request->param('oid')) {
my $oid = $request->param('oid');
$ob = $registry{$oid};
$ob or do { $request->print("no object with that oid"); next; };
} elsif($request->param('path')) {
my @path = split m{/}, $request->param('path');
my $node = $tree;
while(@path) {
my $step = shift @path;
$node = $node->{$step} or do {
$step =~ s{[^a-z0-9:_-]}{}g;
$request->print("step ``$step'' not found in path");
$node = undef;
last;
};
view all matches for this distributionview release on metacpan - search on metacpan
( run in 0.710 second using v1.00-cache-2.02-grep-82fe00e-cpan-2c419f77a38b )