File Coverage

blib/lib/Alice/HTTP/Stream/XHR.pm
Criterion Covered Total %
statement 15 77 19.4
branch 0 18 0.0
condition 0 12 0.0
subroutine 5 19 26.3
pod 1 12 8.3
total 21 138 15.2


line stmt bran cond sub pod time code
1             package Alice::HTTP::Stream::XHR;
2              
3 2     2   1131 use JSON;
  2         13935  
  2         18  
4 2     2   11900 use Time::HiRes qw/time/;
  2         5054  
  2         15  
5 2     2   560 use Any::Moose;
  2         6  
  2         29  
6              
7             extends 'Alice::HTTP::Stream';
8              
9 2     2   1784 use strict;
  2         6  
  2         99  
10 2     2   62 use warnings;
  2         5  
  2         3028  
11              
12             my $separator = "xalicex";
13             our @headers = ('Content-Type' => "multipart/mixed; boundary=$separator; charset=utf-8");
14              
15             has queue => (
16             is => 'rw',
17             isa => 'ArrayRef[HashRef]',
18             default => sub { [] },
19             );
20              
21 0     0 0   sub clear_queue {$_[0]->queue([])}
22 0     0 0   sub enqueue {push @{shift->queue}, @_}
  0            
23 0     0 0   sub queue_empty {return @{$_[0]->queue} == 0}
  0            
24              
25             has [qw/delayed started/] => (
26             is => 'rw',
27             isa => 'Bool',
28             default => 0,
29             );
30              
31             has [qw/offset last_send start_time/]=> (
32             is => 'rw',
33             isa => 'Num',
34             default => 0,
35             );
36              
37             has 'timer' => (
38             is => 'rw',
39             );
40              
41             has 'writer' => (
42             is => 'rw',
43             required => 1,
44             );
45              
46             has min_bytes => (
47             is => 'ro',
48             default => 1024,
49             );
50              
51             sub BUILD {
52 0     0 1   my $self = shift;
53              
54 0           my $local_time = time;
55 0   0       my $remote_time = $self->start_time || $local_time;
56 0           $self->offset($local_time - $remote_time);
57              
58             # better way to get the AE handle?
59 0           my $hdl = $self->writer->{handle};
60              
61 0           $hdl->{rbuf_max} = 1024 * 10;
62              
63             my $close = sub {
64 0     0     $self->close;
65 0           undef $hdl;
66 0           $self->on_error->();
67 0           };
68              
69 0           $hdl->on_eof($close);
70 0           $hdl->on_error($close);
71              
72 0           $self->send([{type => "identify", id => $self->id}]);
73             }
74              
75             sub send {
76 0     0 0   my ($self, $messages) = @_;
77 0 0         return if $self->closed;
78              
79 0 0 0       $messages = [$messages] if $messages and ref $messages ne "ARRAY";
80              
81 0 0 0       $self->enqueue(@$messages) if $messages and @$messages;
82 0 0 0       return if $self->delayed or $self->queue_empty;
83              
84 0 0         if (my $delay = $self->flooded) {
85 0           $self->delay($delay);
86 0           return;
87             }
88 0           $self->send_raw( $self->to_string );
89 0           $self->last_send(time);
90 0           $self->flush;
91             }
92              
93             sub send_raw {
94 0     0 0   my ($self, $string) = @_;
95              
96 0           my $output;
97              
98 0 0         if (! $self->started) {
99 0           $output .= "--$separator\n";
100 0           $self->started(1);
101             }
102            
103 0           $output .= $string;
104              
105 0           $output .= "\n--$separator\n"
106             . " " x ($self->min_bytes - length $output);
107              
108              
109 0           $self->writer->write( $output );
110             }
111              
112             sub ping {
113 0     0 0   my $self = shift;
114 0 0         return if $self->closed;
115 0           $self->send([{type => "action", event => "ping"}]);
116             }
117              
118             sub close {
119 0     0 0   my $self = shift;
120 0           $self->flush;
121 0 0         $self->writer->close if $self->writer;
122 0           $self->writer(undef);
123 0           $self->timer(undef);
124 0           $self->closed(1);
125             }
126              
127             sub flooded {
128 0     0 0   my $self = shift;
129 0           my $diff = time - $self->last_send;
130 0 0         if ($diff < 0.2) {
131 0           return 0.2 - $diff;
132             }
133 0           return 0;
134             }
135              
136             sub delay {
137 0     0 0   my ($self, $delay) = @_;
138 0           $self->delayed(1);
139             $self->timer(AnyEvent->timer(
140             after => $delay,
141             cb => sub {
142 0     0     $self->delayed(0);
143 0           $self->timer(undef);
144 0           $self->send;
145             },
146 0           ));
147             }
148              
149             sub flush {
150 0     0 0   my $self = shift;
151 0           $self->clear_queue;
152 0           $self->last_send(time);
153             }
154              
155             sub to_string {
156 0     0 0   my $self = shift;
157              
158 0           return to_json({
159             queue => $self->queue,
160             time => time - $self->offset,
161             }, {utf8 => 1, shrink => 1});
162             }
163              
164             __PACKAGE__->meta->make_immutable;
165             1;