reverse r4290 since we -do- -not- currently want these namespaces indexed
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema / Role / AtQueryInterval.pm
1 package DBIx::Class::Schema::Role::AtQueryInterval;
2
3 use Moose::Role;
4 use MooseX::AttributeHelpers;
5 use DBIx::Class::Schema::Job;
6 use DBIx::Class::Schema::QueryInterval;
7 use DBIx::Class::Schema::AtQueryInterval;
8
9 =head1 NAME
10
11 DBIx::Class::Schema::Role::AtQueryInterval; Execute code at query intervals
12
13 =head1 SYNOPSIS
14
15 The follow will execute the 'do_something' method each and every 10 queries,
16 excute a subref each 20 queries, and do both each 30 queries.  This first
17 example is the long, hard way.
18     
19     ## ISA DBIx::Class::Schema::Job
20     
21     my $job1 = $schema->create_job(
22         runs => 'do_something',
23     );
24  
25     my $job2 = $schema->create_job(
26         runs => sub {warn 'queries counted'},
27     );
28     
29     
30     ## ISA DBIx::Class::Schema::QueryInterval
31     
32     my $interval_10 = $schema->create_query_interval(every => 10);
33     my $interval_20 = $schema->create_query_interval(every => 20);
34     my $interval_30 = $schema->create_query_interval(every => 30);
35     
36     
37     ## USA DBIx::Class::Schema::AtQueryInterval
38        
39     my $at1 = $schema->create_at_query_interval(
40         interval => $interval_10, job => $job1,
41     );
42
43     my $at2 = $schema->create_at_query_interval(
44         interval => $interval_20, job => $job2,
45     );
46     
47     my $at3 = $schema->create_at_query_interval(
48         interval => $interval_30, job=>$job1,
49     );
50
51     my $at4 = $schema->create_at_query_interval(
52         interval => $interval_30, job=>$job2,
53     );
54     
55     $schema->query_intervals([$1, $at2, $at3, $at4]);
56     
57 Or you can take the express trip (assuming you are not creating any custom
58 Query Intervals, Jobs, etc.)  Notice that this method allows jobs to be defined
59 as an arrayref to make it easier to defined multiple jobs for a given interval.
60
61 In order to perform the needed object instantiation, this class will use the
62 methods 'query_interval_class', 'job_class' and 'at_query_interval_class'.
63
64     $schema->create_and_add_at_query_intervals(
65         {every => 10} => {
66                 runs => 'do_something',
67         },
68         {every => 20} => {
69             runs => sub {
70                 warn 'queries counted';
71             },
72         },        
73         {every => 30} => [
74             {runs => 'do_something'}, 
75             {runs => sub{
76                 warn 'queries counted';
77             }},        
78         ],
79     );
80
81 All the above sit in a DBIx::Class::Schema that consumes the proper roles and 
82 defines a function which receives three arguments:
83     
84     sub do_something {
85         my ($job, $schema, $at_query_interval) = @_;
86     }
87
88 =head1 DESCRIPTION
89
90 Sometime you'd like to perform certain housekeeping activities at preset query
91 intervals.  For example, every 100 queries you want to update a reporting table
92 that contains denormalized information.  This role allows you to assign a
93 scalar containing the name of a method in your schema class, an anonymous sub,
94 or an arrayref of either to a particular interval.
95
96 =head1 ATTRIBUTES
97
98 This package defines the following attributes.
99
100 =head2 query_interval_class
101
102 The default class used to create an interval class from a hash of initializing
103 information.
104
105 =cut
106
107 has 'query_interval_class' => (
108   is=>'ro',
109   isa=>'ClassName',
110   required=>1,
111   default=>'DBIx::Class::Schema::QueryInterval',
112   handles=> {
113         'create_query_interval' => 'new',
114   },
115 );
116
117
118 =head2 job_class
119
120 The default class used to create an job class from a hash of initializing
121 information.
122
123 =cut
124
125 has 'job_class' => (
126   is=>'ro',
127   isa=>'ClassName',
128   required=>1,
129   default=>'DBIx::Class::Schema::Job',
130   handles=> {
131     'create_job' => 'new',
132   },
133 );
134
135
136 =head2 at_query_interval_class
137
138 The default class used to create an job class from a hash of initializing
139 information.
140
141 =cut
142
143 has 'at_query_interval_class' => (
144   is=>'ro',
145   isa=>'ClassName',
146   required=>1,
147   default=>'DBIx::Class::Schema::AtQueryInterval',
148   handles=> {
149     'create_at_query_interval' => 'new',
150   },
151 );
152
153
154 =head2 at_query_intervals
155
156 This is an arrayref of L<DBIx::Class::Schema::AtQueryInterval> objects which 
157 holds all the jobs that need to be run at the given interval.
158
159 =cut
160
161 has 'at_query_intervals' => (
162   is=>'rw',
163   metaclass => 'Collection::Array',
164   auto_deref => 1,
165   isa=>'ArrayRef[DBIx::Class::Schema::AtQueryInterval]',
166   provides => {
167         push => 'add_at_query_interval',
168   },
169 );
170
171
172 =head1 METHODS
173
174 This module defines the following methods.
175
176 =head2 execute_jobs_at_query_interval ($int)
177
178 Execute all the jobs which match the given interval
179
180 =cut
181
182 sub execute_jobs_at_query_interval {
183   my ($self, $query_count, @args) = @_;
184   my @responses;
185   foreach my $at ($self->at_query_intervals) {
186         push @responses,
187           $at->execute_if_matches($query_count, $self, @args);
188   }
189   return @responses;
190 }
191
192
193 =head2 create_and_add_at_query_intervals (%definitions)
194
195 Uses the shortcut method shown above to quickly build a plan from a simple perl
196 array of hashes.
197
198 =cut
199
200 sub create_and_add_at_query_intervals {
201   my ($self, @definitions) = @_;
202   while (@definitions) {
203         my $interval = $self->normalize_query_interval(shift @definitions);
204     my @jobs = $self->normalize_to_jobs(shift @definitions);
205     foreach my $job (@jobs) {
206       my $at = $self->create_at_query_interval(interval=>$interval, job=>$job);
207           $self->add_at_query_interval($at);  
208     }           
209   }
210 }
211  
212
213 =head2 normalize_query_interval ($hash||$obj)
214
215 Given an argument, make sure it's a L<DBIx::Class::Schema::QueryInterval>,
216 coercing it if neccessary.
217
218 =cut
219
220 sub normalize_query_interval {
221   my ($self, $arg) = @_;
222   if(blessed $arg && $arg->isa('DBIx::Class::Schema::QueryInterval')) {
223         return $arg;
224   } else {
225         return $self->create_query_interval($arg);
226   }
227 }
228
229
230 =head2 normalize_to_jobs ($hash||$obj||$arrayref)
231
232 Incoming jobs need to be normalized to an array, so that we can handle adding
233 multiple jobs per interval.
234
235 =cut
236
237 sub normalize_to_jobs {
238   my ($self, $arg) = @_;
239   my @jobs = ref $arg eq 'ARRAY' ? @$arg : ($arg);
240   return map {$self->normalize_job($_)} @jobs;
241 }
242
243
244 =head2 normalize_job ($hash||$obj)
245
246 Given an argument, make sure it's a L<DBIx::Class::Schema::Job>,
247 coercing it if neccessary.
248
249 =cut
250
251 sub normalize_job {
252   my ($self, $arg) = @_;
253   if(blessed $arg && $arg->isa('DBIx::Class::Schema::Job')) {
254     return $arg;
255   } else {
256     return $self->create_job($arg);
257   }
258 }
259
260
261 =head1 AUTHORS
262
263 See L<DBIx::Class> for more information regarding authors.
264
265 =head1 LICENSE
266
267 You may distribute this code under the same terms as Perl itself.
268
269 =cut
270
271
272 1;