File Coverage

blib/lib/GraphQL/PubSub.pm
Criterion Covered Total %
statement 67 67 100.0
branch 17 32 53.1
condition 2 4 50.0
subroutine 14 14 100.0
pod 3 3 100.0
total 103 120 85.8


line stmt bran cond sub pod time code
1              
2             use 5.014;
3 18     18   2241034 use strict;
  18         109  
4 18     18   77 use warnings;
  18         28  
  18         308  
5 18     18   67 use Moo;
  18         27  
  18         412  
6 18     18   78 use GraphQL::Debug qw(_debug);
  18         29  
  18         85  
7 18     18   11164 use Types::TypeTiny -all;
  18         37  
  18         913  
8 18     18   6746 use Types::Standard -all;
  18         46943  
  18         69  
9 18     18   77571 use GraphQL::Type::Library -all;
  18         1049344  
  18         185  
10 18     18   728412 use GraphQL::MaybeTypeCheck;
  18         62  
  18         226  
11 18     18   225007  
  18         141  
  18         83  
12             use constant DEBUG => $ENV{GRAPHQL_DEBUG};
13 18     18   47087  
  18         40  
  18         2045  
14             =head1 NAME
15              
16             GraphQL::PubSub - publish/subscribe
17              
18             =head1 SYNOPSIS
19              
20             use GraphQL::PubSub;
21             my $pubsub = GraphQL::PubSub->new;
22             $pubsub->subscribe('channel1', \&callback);
23             $pubsub->publish('channel1', 1);
24             $pubsub->unsubscribe('channel1', \&callback);
25              
26             =head1 DESCRIPTION
27              
28             Encapsulates the publish/subscribe logic needed by L<GraphQL::Subscription>.
29              
30             =head1 METHODS
31              
32             =head2 subscribe($channel, \&callback[, \&error_callback])
33              
34             Registers the given callback on the given channel.
35              
36             The optional second "error" callback is called as a method on the object
37             when an exception is thrown by the first callback. If not given, the
38             default is for the subscription to be cancelled with L</unsubscribe>. The
39             error callback will be called with values of the channel, the original
40             callback (to enable unsubscribing), the exception thrown, then the values
41             passed to the original callback. Any exceptions will be ignored.
42              
43             =cut
44              
45             has _subscriptions => (is => 'ro', isa => HashRef, default => sub { {} });
46              
47             method _default_error_callback(Str $channel, CodeLike $callback, Any $exception, @values) {
48 1 50   1   7 eval { $self->unsubscribe($channel, $callback) };
  1 50       4  
  1 50       5  
  1 50       7  
  1         14  
  1         12  
  1         12  
49 1         2 }
  1         6  
50              
51             method subscribe(Str $channel, CodeLike $callback, Maybe[CodeLike] $error_callback = undef) {
52 17 50   17 1 4334 $self->_subscriptions->{$channel}{$callback} = [
  17 50       55  
  17 50       34  
  17 50       49  
  17 50       82  
  17         722  
  17         206  
  17         148  
53 17   100     214 $callback,
      0        
54             $error_callback || \&_default_error_callback,
55             ];
56             }
57              
58             =head2 unsubscribe($channel, \&callback)
59              
60             Removes the given callback from the given channel.
61              
62             =cut
63              
64             method unsubscribe(Str $channel, CodeLike $callback) {
65 2 50   2 1 2040 delete $self->_subscriptions->{$channel}{$callback};
  2 50       10  
  2 50       5  
  2 50       8  
  2         14  
  2         91  
  2         28  
66 2         16 }
67              
68             =head2 publish($channel, @values)
69              
70             Calls each callback registered on the given channel, with the given values.
71              
72             =cut
73              
74             method publish(Str $channel, @values) {
75 21 50   21 1 6237 for my $cb (values %{ $self->_subscriptions->{$channel} }) {
  21 50       58  
  21         48  
  21         72  
  21         222  
76 21         37 my ($normal, $error) = @$cb;
  21         103  
77 22         52 eval { $normal->(@values) };
78 22         47 eval { $self->$error($channel, $normal, $@, @values) } if $@;
  22         74  
79 22 100       642 }
  2         10  
80             }
81              
82             __PACKAGE__->meta->make_immutable();
83              
84             1;