File Coverage

blib/lib/Bot/Backbone/Bot.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Bot::Backbone::Bot;
2             $Bot::Backbone::Bot::VERSION = '0.142820';
3 3     3   4556 use v5.10;
  3         12  
  3         130  
4 3     3   14 use Moose;
  3         3  
  3         19  
5              
6 3     3   14849 use Bot::Backbone::Types qw( EventLoop ServiceList );
  3         7  
  3         25  
7 3     3   5206 use POE qw( Loop::AnyEvent );
  0            
  0            
8              
9             # ABSTRACT: Provides backbone services to your bot
10              
11              
12             has event_loop => (
13             is => 'ro',
14             isa => EventLoop,
15             required => 1,
16             default => 'POE::Kernel',
17             );
18              
19              
20             has services => (
21             is => 'ro',
22             isa => ServiceList,
23             required => 1,
24             default => sub { +{} },
25             traits => [ 'Hash' ],
26             handles => {
27             add_service => 'set',
28             list_services => 'values',
29             destroy_services => 'clear',
30             has_service => 'defined',
31             get_service => 'get',
32             },
33             );
34              
35              
36             sub bot { $_[0] }
37              
38              
39             sub construct_services {
40             my $self = shift;
41              
42             my $my_name = $self->meta->name;
43              
44             for my $name ($self->meta->list_services) {
45             my $service_config = $self->meta->services->{$name};
46             next if defined $self->services->{$name};
47              
48             my $class_name = $service_config->{service};
49             my $service = $class_name->new(
50             %$service_config,
51             name => $name,
52             bot => $self,
53             );
54              
55             $self->add_service($name, $service);
56             }
57             }
58              
59              
60             sub run {
61             my $self = shift;
62              
63             $self->construct_services;
64             $_->initialize for ($self->list_services);
65              
66             $self->event_loop->run;
67             }
68              
69              
70             sub shutdown {
71             my $self = shift;
72              
73             $_->shutdown for ($self->list_services);
74             $self->destroy_services;
75             }
76              
77              
78             __PACKAGE__->meta->make_immutable;
79              
80             __END__
81              
82             =pod
83              
84             =encoding UTF-8
85              
86             =head1 NAME
87              
88             Bot::Backbone::Bot - Provides backbone services to your bot
89              
90             =head1 VERSION
91              
92             version 0.142820
93              
94             =head1 SYNOPSIS
95              
96             my $bot = My::Bot->new;
97             $bot->run;
98              
99             =head1 DESCRIPTION
100              
101             When you use L<Bot::Backbone> in your code, you get a bot implementing this
102             role. It provides tools for constructing, executing, and shutting down services.
103              
104             =head1 ATTRIBUTES
105              
106             =head2 event_loop
107              
108             Bots do all their work using an event loop. Usually, this is either L<POE> or
109             L<AnyEvent>. Fortunately, these event loops tend to work well together in case
110             you need both. Just in case you need specialized startup for your bot's event
111             loop, though, this is attribute is provided to allow the event loop startup to
112             be customized.
113              
114             This is an object or class on which you may call a C<run> with no arguments. It
115             will be called to start the event loop. By default, this is just
116             "L<POE::Kernel>". It is expected that this method will block until the bot is
117             shutdown.
118              
119             =head2 services
120              
121             This is a hash of constructed services used by this bot. There should be a key
122             in this hash matching every key in the same attribute in
123             L<Bot::Backbone::Meta::Class>, once L</run> has been called.
124              
125             =head1 METHODS
126              
127             =head2 bot
128              
129             Returns itself.
130              
131             =head2 construct_services
132              
133             $bot->construct_services;
134              
135             This method iterates through the service configurations of the meta class and constructs each service from that configuration.
136              
137             You may run this prior to L</run> to construct your services prior to running. Normally, though, this method is called within L</run>.
138              
139             =head2 run
140              
141             $bot->run;
142              
143             This starts your bot running. It constructs the services if they have not yet been constructed. Then, it initializes each service. Finally, it starts the L<POE> event loop. This last part really isn't it's business and might go away in the future.
144              
145             This method will not return until the event loop terminates. The usual way to do this is to call L</shutdown>.
146              
147             =head2 shutdown
148              
149             $bot->shutdown;
150              
151             You may call this at any time while your bot is running to shutdown all the services. This notifies each service that it should shutdown (i.e., finish or terminate any pending jobs in the event loop). It then clears the L</services> hash, which should cause all services to be destroyed.
152              
153             =head1 CAVEATS
154              
155             This thing sort of kind of needs L<POE> to be any kind of useful. However, L<POE> seems to have weird drawbacks. I have some planned work-arounds for this being an explicit and required dependency, but it's there for now.
156              
157             Second, if you use the Jabber chat service, you need L<AnyEvent>. Mostly, L<AnyEvent> and L<POE> seem to get along, but it's slow and I've found that timers, in particular, just plain don't work quite right.
158              
159             =head1 AUTHOR
160              
161             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
162              
163             =head1 COPYRIGHT AND LICENSE
164              
165             This software is copyright (c) 2014 by Qubling Software LLC.
166              
167             This is free software; you can redistribute it and/or modify it under
168             the same terms as the Perl 5 programming language system itself.
169              
170             =cut