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