File Coverage

blib/lib/AnyEvent/Plackup.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package AnyEvent::Plackup;
2 2     2   309907 use strict;
  2         6  
  2         99  
3 2     2   16 use warnings;
  2         5  
  2         78  
4 2     2   67 use 5.008_001;
  2         22  
  2         112  
5             use overload (
6 2         21 '""' => 'origin',
7             fallback => 1
8 2     2   13 );
  2         5  
9              
10 2     2   4433 use AnyEvent;
  2         14517  
  2         67  
11 2     2   2456 use Twiggy::Server;
  0            
  0            
12             use Net::EmptyPort qw(empty_port);
13             use Scalar::Util qw(weaken);
14             use Carp;
15              
16             use Class::Accessor::Lite (
17             ro => [
18             'host', 'port',
19             'ready_cv', 'request_cv',
20             'twiggy',
21             ],
22             );
23              
24             use Exporter::Lite;
25              
26             our $VERSION = '0.02';
27             our @EXPORT = qw(plackup);
28              
29             sub plackup (@) {
30             return __PACKAGE__->new(@_);
31             }
32              
33             sub new {
34             my ($class, %args) = @_;
35             my $self = bless {
36             app => delete $args{app},
37             args => \%args,
38             }, $class;
39             $self->_run;
40             return $self;
41             }
42              
43             sub recv {
44             my $self = shift;
45              
46             croak 'plackup->recv is not available if app is set'
47             if $self->{app};
48              
49             unless (@{ $self->{request_queue} }) {
50             $self->{request_cv} = AE::cv if $self->{request_cv}->ready;
51             $self->{request_cv}->recv;
52             }
53              
54             return shift @{ $self->{request_queue} };
55             }
56              
57             sub origin {
58             my $self = shift;
59             return sprintf "http://%s:%s", $self->host, $self->port;
60             }
61              
62             sub _run {
63             my $self = shift;
64              
65             weaken $self;
66              
67             $self->{ready_cv} = AE::cv;
68              
69             my $app = $self->{app} || $self->_mk_default_app;
70              
71             my $twiggy = Twiggy::Server->new(
72             port => $self->{port} || empty_port(),
73             %{ $self->{args} || {} },
74             server_ready => sub {
75             my $args = shift;
76              
77             $self->{host} = $args->{host};
78             $self->{port} = $args->{port};
79              
80             $self->ready_cv->send($args);
81             }
82             );
83             $twiggy->register_service($app);
84              
85             $self->{twiggy} = $twiggy;
86             }
87              
88             sub _mk_default_app {
89             my $self = shift;
90              
91             $self->{request_cv} = AE::cv;
92             $self->{request_queue} = [];
93              
94             weaken $self;
95              
96             require AnyEvent::Plackup::Request;
97              
98             return sub {
99             my ($env) = @_;
100              
101             my $req = AnyEvent::Plackup::Request->new($env);
102              
103             push @{ $self->{request_queue} }, $req;
104             $self->{request_cv}->send if $self->{request_cv};
105              
106             return sub {
107             my $respond = shift;
108             $req->_response_cv->cb(sub {
109             my $res = $_[0]->recv;
110             if (ref $res eq 'CODE') {
111             $res->($respond);
112             } else {
113             $respond->($res);
114             }
115             });
116             };
117             };
118             }
119              
120             sub DESTROY {
121             my $self = shift;
122             local $@;
123             delete $self->{twiggy}->{listen_guards};
124             }
125              
126             sub shutdown {
127             my $self = shift;
128             my $w; $w = AE::timer 0, 0, sub {
129             $self->{twiggy}->{exit_guard}->end;
130             undef $w;
131             };
132             $self->{twiggy}->{exit_guard}->recv;
133             }
134              
135             1;
136              
137             __END__