refactored the duties of the different balancer classes, added tests and docs
[dbsrgits/DBIx-Class-Historic.git] / lib / DBIx / Class / Storage / DBI / Replicated / Balancer.pm
index 6221bdd..bf47c07 100644 (file)
@@ -1,7 +1,6 @@
 package DBIx::Class::Storage::DBI::Replicated::Balancer;
 
 use Moose;
-use List::Util qw(shuffle);
 
 =head1 NAME
 
@@ -22,26 +21,114 @@ method by which query load can be spread out across each replicant in the pool.
 
 This class defines the following attributes.
 
+=head2 pool
+
+The L<DBIx::Class::Storage::DBI::Replicated::Pool> object that we are trying to
+balance.
+
+=cut
+
+has 'pool' => (
+    is=>'ro',
+    isa=>'DBIx::Class::Storage::DBI::Replicated::Pool',
+    required=>1,
+);
+
+=head2 current_replicant
+
+Replicant storages (slaves) handle all read only traffic.  The assumption is
+that your database will become readbound well before it becomes write bound
+and that being able to spread your read only traffic around to multiple 
+databases is going to help you to scale traffic.
+
+This attribute returns the next slave to handle a read request.  Your L</pool>
+attribute has methods to help you shuffle through all the available replicants
+via it's balancer object.
+
+=cut
+
+has 'current_replicant' => (
+    is=> 'rw',
+    isa=>'DBIx::Class::Storage::DBI',
+    lazy_build=>1,
+    handles=>[qw/
+        select
+        select_single
+        columns_info_for
+    /],
+);
+
 =head1 METHODS
 
 This class defines the following methods.
 
-=head2 next_storage ($pool)
+=head2 _build_current_replicant
+
+Lazy builder for the L</current_replicant_storage> attribute.
+
+=cut
+
+sub _build_current_replicant {
+    my $self = shift @_;
+    $self->next_storage($self->pool);
+}
+
+=head2 next_storage
 
 Given a pool object, return the next replicant that will serve queries.  The
-default behavior is to randomize but you can write your own subclasses of
-L<DBIx::Class::Storage::DBI::Replicated::Balancer> to support other balance
-systems.
+default behavior is to grap the first replicant it finds but you can write 
+your own subclasses of L<DBIx::Class::Storage::DBI::Replicated::Balancer> to 
+support other balance systems.
 
 =cut
 
 sub next_storage {
        my $self = shift @_;
-       my $pool = shift @_;
-       
-       return (shuffle($pool->active_replicants))[0];
+       return ($self->pool->active_replicants)[0]
+         if $self->pool->active_replicants;
 }
 
+=head2 after: select
+
+Advice on the select attribute.  Each time we use a replicant
+we need to change it via the storage pool algorithm.  That way we are spreading
+the load evenly (hopefully) across existing capacity.
+
+=cut
+
+after 'select' => sub {
+    my $self = shift @_;
+    my $next_replicant = $self->next_storage;
+    $self->current_replicant($next_replicant);
+};
+
+=head2 after: select_single
+
+Advice on the select_single attribute.  Each time we use a replicant
+we need to change it via the storage pool algorithm.  That way we are spreading
+the load evenly (hopefully) across existing capacity.
+
+=cut
+
+after 'select_single' => sub {
+    my $self = shift @_;
+    my $next_replicant = $self->next_storage;
+    $self->current_replicant($next_replicant);
+};
+
+=head2 after: columns_info_for
+
+Advice on the current_replicant_storage attribute.  Each time we use a replicant
+we need to change it via the storage pool algorithm.  That way we are spreading
+the load evenly (hopefully) across existing capacity.
+
+=cut
+
+after 'columns_info_for' => sub {
+    my $self = shift @_;
+    my $next_replicant = $self->next_storage;
+    $self->current_replicant($next_replicant);
+};
 
 =head1 AUTHOR
 
@@ -53,4 +140,4 @@ You may distribute this code under the same terms as Perl itself.
 
 =cut
 
-1;
\ No newline at end of file
+1;