line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
use 5.014; |
3
|
2
|
|
|
2
|
|
1120
|
use strict; |
|
40
|
|
|
|
|
361
|
|
4
|
40
|
|
|
2
|
|
322
|
use warnings; |
|
20
|
|
|
|
|
257
|
|
|
2
|
|
|
|
|
46
|
|
5
|
2
|
|
|
2
|
|
10
|
use Moo; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
70
|
|
6
|
2
|
|
|
2
|
|
11
|
use GraphQL::Debug qw(_debug); |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
16
|
|
7
|
2
|
|
|
2
|
|
745
|
use Types::Standard -all; |
|
2
|
|
|
|
|
38
|
|
|
2
|
|
|
|
|
134
|
|
8
|
2
|
|
|
2
|
|
13
|
use Types::TypeTiny -all; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
40
|
|
9
|
2
|
|
|
2
|
|
82108
|
use GraphQL::Type::Library -all; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
14
|
|
10
|
2
|
|
|
2
|
|
1283
|
use GraphQL::PubSub; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
24
|
|
11
|
2
|
|
|
2
|
|
24929
|
use GraphQL::MaybeTypeCheck; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
35
|
|
12
|
2
|
|
|
2
|
|
11
|
use curry; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
9
|
|
13
|
2
|
|
|
2
|
|
10
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
73
|
|
14
|
|
|
|
|
|
|
use constant DEBUG => $ENV{GRAPHQL_DEBUG}; |
15
|
2
|
|
|
2
|
|
10
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
415
|
|
16
|
|
|
|
|
|
|
=head1 NAME |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
GraphQL::AsyncIterator - iterator objects that return promise to next result |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 SYNOPSIS |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
use GraphQL::AsyncIterator; |
23
|
|
|
|
|
|
|
my $i = GraphQL::AsyncIterator->new( |
24
|
|
|
|
|
|
|
promise_code => $pc, |
25
|
|
|
|
|
|
|
); |
26
|
|
|
|
|
|
|
# also works when publish happens before next_p called |
27
|
|
|
|
|
|
|
my $promised_value = $i->next_p; |
28
|
|
|
|
|
|
|
$i->publish('hi'); # now $promised_value will be fulfilled |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
$i->close_tap; # now next_p will return undef |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 DESCRIPTION |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Encapsulates the asynchronous event-handling needed for the |
35
|
|
|
|
|
|
|
publish/subscribe behaviour needed by L<GraphQL::Subscription>. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head2 promise_code |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
A hash-ref matching L<GraphQL::Type::Library/PromiseCode>, which must |
42
|
|
|
|
|
|
|
provide the C<new> key. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=cut |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
has promise_code => (is => 'ro', isa => PromiseCode); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 METHODS |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head2 publish(@values) |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Resolves the relevant promise with C<@values>. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=cut |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
has _values_queue => (is => 'ro', isa => ArrayRef, default => sub { [] }); |
57
|
|
|
|
|
|
|
has _next_promise => (is => 'rw', isa => Maybe[Promise]); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
method publish(@values) { |
60
|
22
|
50
|
|
22
|
1
|
4828
|
$self->_emit('resolve', \@values); |
|
22
|
|
|
|
|
44
|
|
|
22
|
|
|
|
|
52
|
|
|
22
|
|
|
|
|
37
|
|
61
|
22
|
|
|
|
|
96
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
method _promisify((Enum[qw(resolve reject)]) $method, $data) { |
64
|
38
|
50
|
|
38
|
|
107
|
return $data if is_Promise($data); |
|
38
|
50
|
|
|
|
399
|
|
|
38
|
50
|
|
|
|
82
|
|
|
38
|
|
|
|
|
73
|
|
|
38
|
|
|
|
|
141
|
|
|
20
|
|
|
|
|
368
|
|
65
|
20
|
50
|
|
|
|
76
|
$self->promise_code->{$method}->(@$data); |
66
|
20
|
|
|
|
|
41
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
method _thenify(Maybe[CodeLike] $then, Maybe[CodeLike] $catch, (Enum[qw(resolve reject)]) $method, $data) { |
69
|
20
|
50
|
|
20
|
|
60
|
return $data unless $then or $catch; |
|
20
|
50
|
|
|
|
79
|
|
|
20
|
50
|
|
|
|
284
|
|
|
20
|
50
|
|
|
|
195
|
|
|
20
|
50
|
|
|
|
290
|
|
|
20
|
|
|
|
|
70
|
|
|
20
|
|
|
|
|
62
|
|
|
25
|
|
|
|
|
75
|
|
70
|
25
|
50
|
33
|
|
|
70
|
$self->_promisify($method, $data)->then($then, $catch); |
71
|
25
|
|
|
|
|
46
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
method _emit((Enum[qw(resolve reject)]) $method, $data) { |
74
|
25
|
50
|
|
25
|
|
53
|
if ($self->_exhausted) { |
|
25
|
100
|
|
|
|
126
|
|
|
25
|
50
|
|
|
|
468
|
|
|
25
|
|
|
|
|
482
|
|
|
1
|
|
|
|
|
15
|
|
|
24
|
|
|
|
|
501
|
|
75
|
6
|
100
|
|
|
|
85
|
die "Tried to emit to closed-off AsyncIterator\n"; |
76
|
6
|
|
|
|
|
278
|
} |
77
|
|
|
|
|
|
|
if (my $next_promise = $self->_next_promise) { |
78
|
18
|
50
|
|
|
|
120
|
$next_promise->$method(ref $data eq 'ARRAY' ? @$data : $data); |
79
|
18
|
50
|
|
|
|
116
|
$self->_next_promise(undef); |
80
|
3
|
|
|
|
|
164
|
} else { |
81
|
|
|
|
|
|
|
push @{$self->_values_queue}, { data => $data, method => $method }; |
82
|
3
|
|
|
|
|
9
|
} |
|
3
|
|
|
|
|
12
|
|
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head2 error(@values) |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Rejects the relevant promise with C<@values>. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=cut |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
method error(@values) { |
92
|
3
|
50
|
|
3
|
1
|
4
|
$self->_emit('reject', \@values); |
|
3
|
|
|
|
|
17
|
|
|
11
|
|
|
|
|
61
|
|
|
11
|
|
|
|
|
35
|
|
93
|
11
|
|
|
|
|
24
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head2 next_p |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
Returns either a L<GraphQL::Type::Library/Promise> of the next value, |
98
|
|
|
|
|
|
|
or C<undef> when closed off. Do not call this if a previous promised next |
99
|
|
|
|
|
|
|
value has not been settled, as a queue is not maintained. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
The promise will have each of the sets of handlers added by L</map_then> |
102
|
|
|
|
|
|
|
appended. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=cut |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
method next_p() :ReturnType(Maybe[Promise]) { |
107
|
27
|
50
|
|
27
|
1
|
6664
|
return undef if $self->_exhausted and !@{$self->_values_queue}; |
|
27
|
50
|
|
|
|
103
|
|
|
27
|
|
|
|
|
65
|
|
|
27
|
|
|
|
|
49
|
|
108
|
27
|
100
|
100
|
|
|
530
|
my $np; |
|
5
|
|
|
|
|
73
|
|
109
|
24
|
|
|
|
|
194
|
if (my $value = shift @{$self->_values_queue}) { |
110
|
24
|
100
|
|
|
|
45
|
$np = $self->_promisify(@$value{qw(method data)}); |
|
24
|
|
|
|
|
128
|
|
111
|
18
|
|
|
|
|
84
|
} else { |
112
|
|
|
|
|
|
|
$np = $self->_next_promise($self->promise_code->{new}->()); |
113
|
6
|
|
|
|
|
43
|
} |
114
|
|
|
|
|
|
|
$np = $self->_thenify(@$_, 'resolve', $np) for @{$self->_handler_frames}; |
115
|
24
|
|
|
|
|
1920
|
$np; |
|
24
|
|
|
|
|
165
|
|
116
|
24
|
|
|
|
|
938
|
} |
117
|
2
|
|
|
2
|
|
4756
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
16
|
|
118
|
|
|
|
|
|
|
=head2 close_tap |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Switch to being closed off. L</next_p> will return C<undef> as soon as |
121
|
|
|
|
|
|
|
it runs out of L</publish>ed values. L</publish> will throw an exception. |
122
|
|
|
|
|
|
|
B<NB> This will not cause the settling of any outstanding promise returned |
123
|
|
|
|
|
|
|
by L</next_p>. |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=cut |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
has _exhausted => (is => 'rw', isa => Bool, default => sub { 0 }); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
method close_tap() :ReturnType(Maybe[Promise]) { |
130
|
3
|
50
|
|
3
|
1
|
91
|
return if $self->_exhausted; # already done - no need to redo |
|
3
|
50
|
|
|
|
15
|
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
7
|
|
131
|
3
|
50
|
|
|
|
77
|
$self->_exhausted(1); |
132
|
3
|
|
|
|
|
74
|
} |
133
|
2
|
|
|
2
|
|
6831
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
11
|
|
134
|
|
|
|
|
|
|
=head2 map_then($then, $catch) |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Adds the handlers to this object's list of handlers, which will be |
137
|
|
|
|
|
|
|
attached to promises returned by L</next_p>. Returns self. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=cut |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
has _handler_frames => ( |
142
|
|
|
|
|
|
|
is => 'ro', isa => ArrayRef[ArrayRef[CodeLike]], default => sub {[]}, |
143
|
|
|
|
|
|
|
); |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
method map_then(Maybe[CodeLike] $then, Maybe[CodeLike] $catch = undef) { |
146
|
11
|
50
|
|
11
|
1
|
30
|
push @{$self->_handler_frames}, [ $then, $catch ]; |
|
11
|
50
|
|
|
|
54
|
|
|
11
|
|
|
|
|
224
|
|
|
11
|
|
|
|
|
87
|
|
|
11
|
|
|
|
|
18
|
|
|
11
|
|
|
|
|
56
|
|
|
11
|
|
|
|
|
102
|
|
147
|
|
|
|
|
|
|
$self; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable(); |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
1; |