File Coverage

blib/lib/Net/NodeTransformator.pm
Criterion Covered Total %
statement 36 112 32.1
branch 0 38 0.0
condition 0 25 0.0
subroutine 12 25 48.0
pod 10 10 100.0
total 58 210 27.6


line stmt bran cond sub pod time code
1 2     2   85984 use strict;
  2         4  
  2         86  
2 2     2   11 use warnings;
  2         3  
  2         80  
3              
4             package Net::NodeTransformator;
5              
6             # ABSTRACT: interface to node transformator
7              
8 2     2   2040 use AnyEvent;
  2         9974  
  2         85  
9 2     2   1818 use AnyEvent::Handle;
  2         36177  
  2         114  
10 2     2   1670 use AnyEvent::Socket;
  2         25679  
  2         284  
11 2     2   1308 use AnyEvent::Proc 0.101;
  2         73874  
  2         144  
12 2     2   21 use Try::Tiny;
  2         4  
  2         128  
13 2     2   495 use Env::Path;
  2         2059  
  2         17  
14 2     2   2028 use File::Temp qw(tempdir);
  2         40497  
  2         149  
15 2     2   28 use POSIX qw(getcwd);
  2         3  
  2         17  
16 2     2   2048 use CBOR::XS ();
  2         8111  
  2         58  
17 2     2   17 use Carp;
  2         3  
  2         2140  
18              
19             our $VERSION = '0.105'; # VERSION
20              
21             sub new {
22 0     0 1   my ( $class, $hostport ) = @_;
23 0 0         if ( $hostport !~ m{:} ) {
24 0 0         if ( $hostport =~ m{^\d+$} ) {
25 0           $hostport = "localhost:$hostport";
26             }
27             else {
28 0           $hostport = "unix/:$hostport";
29             }
30             }
31 0           my ( $host, $port ) = parse_hostport($hostport);
32 0 0 0       if ( $host eq 'unix/' and $port !~ m{^/} ) {
33 0           $port = getcwd . '/' . $port;
34             }
35             bless {
36 0   0       host => $host,
37             port => $port,
38             } => ref $class
39             || $class;
40             }
41              
42             sub standalone {
43 0     0 1   my $class = shift;
44              
45 0           my %options;
46 0 0 0       if ( @_ > 1 and !( @_ % 2 ) ) {
    0          
    0          
47 0           %options = @_;
48             }
49             elsif ( @_ == 1 ) {
50 0           $options{connect} = shift;
51             }
52             elsif (@_) {
53 0           croak "wrong paramater given for $class->standalone";
54             }
55              
56 0   0       $options{bin} ||= 'transformator';
57 0 0         my $path =
58             $options{bin} =~ m{/}
59             ? $options{bin}
60             : ( Env::Path->PATH->Whence( $options{bin} ) )[0];
61              
62 0 0         unless ($path) {
63 0           croak "binary " . $options{bin} . " not found";
64             }
65              
66 0 0         unless ( $options{connect} ) {
67 0           my $tmpdir = tempdir( CLEANUP => 1 );
68 0           $options{connect} = "$tmpdir/~sock";
69             }
70              
71 0           my $errstr = '';
72              
73 0   0       my $cv = $options{cv} // AE::cv;
74              
75             my $server = AnyEvent::Proc->new(
76             bin => $path,
77             args => [ $options{connect} ],
78             rtimeout => 10,
79             errstr => \$errstr,
80             on_rtimeout => sub {
81             shift->fire_and_kill(
82             10,
83             sub {
84 0           $cv->croak( 'timeout (' . $errstr . ')' );
85             }
86 0     0     );
87             },
88 0           );
89              
90             $server->readlines_cb(
91             sub {
92 0 0   0     if ( shift =~ m{server bound} ) {
93 0           $server->stop_rtimeout;
94 0           my $client = $class->new( $options{connect} );
95 0           $client->{_server} = $server;
96 0           $cv->send($client);
97             }
98             }
99 0           );
100              
101 0 0 0       if ( $options{cb} or $options{cv} ) {
102 0 0         $cv->cb( $options{cb} ) if $options{cb};
103 0           return $cv;
104             }
105             else {
106 0           return $cv->recv;
107             }
108             }
109              
110             sub cleanup {
111 0     0 1   my ($self) = @_;
112 0 0         if ( exists $self->{_server} ) {
113 0           my $server = delete $self->{_server};
114 0           $server->fire_and_kill(10);
115             }
116             else {
117 0           AE::log note =>
118             "$self->cleanup called when no standalone server active";
119             }
120              
121             }
122              
123             sub transform_cv {
124 0     0 1   my ( $self, %options ) = @_;
125              
126 0 0         if ( $options{on_error} ) {
127 0           confess
128             "on_error option is deprecated. the returned condvar will now croak on receive if there is an error.";
129             }
130              
131 0   0       my $cv = $options{cv} || AE::cv;
132              
133 0           my $host = $self->{host};
134 0           my $port = $self->{port};
135              
136             tcp_connect(
137             $host, $port,
138             sub {
139 0 0   0     return $cv->croak("Connect to $host:$port failed: $!") unless @_;
140 0           my ($fh) = @_;
141 0           my $AEH;
142             $AEH = AnyEvent::Handle->new(
143             fh => $fh,
144             on_error => sub {
145 0           my ( $handle, $fatal, $message ) = @_;
146 0           $handle->destroy;
147 0           $cv->croak("Socket error: $message");
148             },
149             on_eof => sub {
150 0           $AEH->destroy;
151             },
152 0           );
153             $AEH->push_read(
154             cbor => sub {
155 0           my $answer = $_[1];
156 0 0 0       if ( defined $answer and ref $answer eq 'HASH' ) {
157 0 0         if ( exists $answer->{error} ) {
    0          
158 0           $cv->croak( "Service error: " . $answer->{error} );
159             }
160             elsif ( exists $answer->{result} ) {
161 0           $cv->send( $answer->{result} );
162             }
163             else {
164 0           $cv->croak(
165             "Something is wrong: no result and no error");
166             }
167             }
168             else {
169 0           $cv->croak("No answer");
170             }
171             }
172 0           );
173 0   0       $AEH->push_write( cbor =>
174             [ $options{engine}, $options{input}, $options{data} || {} ] );
175 0           $AEH->push_shutdown;
176             }
177 0           );
178              
179 0 0         $cv->cb( $options{cb} ) if $options{cb};
180              
181 0           $cv;
182             }
183              
184             sub transform {
185 0     0 1   my ( $self, $engine, $input, $data ) = @_;
186 0           $self->transform_cv(
187             engine => $engine,
188             input => $input,
189             data => $data,
190             )->recv;
191             }
192              
193 0     0 1   sub jade { shift->transform( jade => @_ ) }
194              
195 0     0 1   sub coffeescript { shift->transform( coffeescript => @_ ) }
196              
197 0     0 1   sub minify_html { shift->transform( minify_html => @_ ) }
198              
199 0     0 1   sub minify_css { shift->transform( minify_css => @_ ) }
200              
201 0     0 1   sub minify_js { shift->transform( minify_js => @_ ) }
202              
203             1;
204              
205             __END__