File Coverage

blib/lib/Gearman/Driver/Console.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Gearman::Driver::Console;
2              
3 1     1   4577 use Moose;
  0            
  0            
4             use POE qw(Component::Server::TCP);
5             use Module::Find;
6             use Moose::Util qw(apply_all_roles);
7             use Try::Tiny;
8              
9             =head1 NAME
10              
11             Gearman::Driver::Console - Management console
12              
13             =head1 SYNOPSIS
14              
15             $ ~/Gearman-Driver$ gearman_driver.pl --console_port 12345 &
16             [1] 32890
17             $ ~/Gearman-Driver$ telnet localhost 12345
18             Trying ::1...
19             telnet: connect to address ::1: Connection refused
20             Trying fe80::1...
21             telnet: connect to address fe80::1: Connection refused
22             Trying 127.0.0.1...
23             Connected to localhost.
24             Escape character is '^]'.
25             status
26             GDExamples::Convert::convert_to_jpeg 0 5 0 2010-01-29T20:37:17 1970-01-01T00:00:00
27             GDExamples::Convert::convert_to_gif 0 5 0 2010-01-29T20:37:12 2010-01-29T20:37:12 some error
28             .
29              
30             =head1 DESCRIPTION
31              
32             By default L<Gearman::Driver> provides a management console which can
33             be used with a standard telnet client. It's possible to list all
34             running worker processes as well as changing min/max processes
35             on runtime.
36              
37             Each successful L<command|/COMMANDS> ends with a dot. If a
38             command throws an error, a line starting with 'ERR' will be
39             returned.
40              
41             =cut
42              
43             has 'port' => (
44             is => 'rw',
45             isa => 'Int',
46             required => 1,
47             );
48              
49             has 'server' => (
50             is => 'ro',
51             isa => 'POE::Component::Server::TCP',
52             );
53              
54             has 'driver' => (
55             handles => { log => 'log' },
56             is => 'rw',
57             isa => 'Gearman::Driver',
58             required => 1,
59             weak_ref => 1,
60             );
61              
62             sub BUILD {
63             my ($self) = @_;
64              
65             my @commands = grep $_ ne 'Gearman::Driver::Console::Client', findallmod Gearman::Driver::Console;
66             apply_all_roles( $self => @commands );
67              
68             $self->{server} = POE::Component::Server::TCP->new(
69             Alias => "server",
70             Port => $self->port,
71             ClientError => sub { },
72             ClientInput => sub {
73             my ( $session, $heap, $input ) = @_[ SESSION, HEAP, ARG0 ];
74             my ( $command, @params ) = split /\s+/, $input;
75             $command ||= '';
76              
77             if ( $self->can($command) ) {
78             try {
79             my @result = $self->$command(@params);
80             try {
81             $heap->{client}->put($_) for @result;
82             };
83             }
84             catch {
85             chomp($_);
86             try {
87             $heap->{client}->put($_);
88             };
89             };
90             }
91              
92             elsif ( $command eq 'quit' ) {
93             delete $heap->{client};
94             return;
95             }
96              
97             else {
98             try {
99             $heap->{client}->put("ERR unknown_command: $command");
100             };
101             }
102              
103             try {
104             $heap->{client}->put('.');
105             };
106             }
107             );
108             }
109              
110             =head1 COMMANDS
111              
112             All basic commands are implemented in
113             L<Gearman::Driver::Console::Basic>. It's very easy to extend this
114             console with new commands. Every module found in namespace
115             C<Gearman::Driver::Console::*> will be loaded. Each of those
116             modules has to be implemented as a L<Moose::Role>. You've got
117             access to two attributes/methods there:
118              
119             =over 4
120              
121             =item * C<driver> - reference to the L<Gearman::Driver> object
122              
123             =item * C<server> - reference to the L<POE::Component::TCP::Server> object
124              
125             =item * C<get_job($name)> - returns a L<Gearman::Driver::Job> object
126              
127             =back
128              
129             So a new command could look like:
130              
131             package Gearman::Driver::Console::List;
132              
133             use Moose::Role;
134              
135             sub list {
136             my ($self) = @_;
137             my @result = ();
138             foreach my $job ( $self->driver->get_jobs ) {
139             push @result, $job->name;
140             }
141             return @result;
142             }
143              
144             1;
145              
146             If you need to throw an error, just die and everything will work as
147             expected (as long as you do not forget the C<\n>):
148              
149             package Gearman::Driver::Console::Broken;
150              
151             use Moose::Role;
152              
153             sub broken {
154             my ($self) = @_;
155             die "ERR this is a broken command\n";
156             }
157              
158             sub get_max_processes {
159             my ( $self, $job_name ) = @_;
160             my $job = $self->get_job($job_name); # this automatically dies if job is not found
161             return $job->max_processes;
162             }
163              
164             1;
165              
166             Yes, that's all...
167              
168             $ ~/Gearman-Driver$ telnet localhost 47300
169             Trying ::1...
170             telnet: connect to address ::1: Connection refused
171             Trying fe80::1...
172             telnet: connect to address fe80::1: Connection refused
173             Trying 127.0.0.1...
174             Connected to localhost.
175             Escape character is '^]'.
176             list
177             GDExamples::Convert::convert_to_jpeg
178             GDExamples::Convert::convert_to_gif
179             .
180             broken
181             ERR this is a broken command
182             get_max_processes asdf
183             ERR invalid_job_name: asdf
184             get_max_processes GDExamples::Convert::convert_to_jpeg
185             6
186             .
187              
188             =cut
189              
190             sub get_job {
191             my ( $self, $job_name ) = @_;
192             return $self->driver->get_job($job_name) || die "ERR invalid_job_name: $job_name\n";
193             }
194              
195             no Moose;
196              
197             __PACKAGE__->meta->make_immutable;
198              
199             =head1 AUTHOR
200              
201             See L<Gearman::Driver>.
202              
203             =head1 COPYRIGHT AND LICENSE
204              
205             See L<Gearman::Driver>.
206              
207             =head1 SEE ALSO
208              
209             =over 4
210              
211             =item * L<Gearman::Driver>
212              
213             =item * L<Gearman::Driver::Adaptor>
214              
215             =item * L<Gearman::Driver::Console::Basic>
216              
217             =item * L<Gearman::Driver::Console::Client>
218              
219             =item * L<Gearman::Driver::Job>
220              
221             =item * L<Gearman::Driver::Job::Method>
222              
223             =item * L<Gearman::Driver::Loader>
224              
225             =item * L<Gearman::Driver::Observer>
226              
227             =item * L<Gearman::Driver::Worker>
228              
229             =back
230              
231             =cut
232              
233             1;