X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI%2FReplicated%2FBalancer.pm;h=26e35809f5689b17abf319093165cb76342c7c0f;hb=12a184d0a0c1868708e43aaabefe08f9e7ac9ec4;hp=0925dec44cf66023f552d52d2a40014082e3750e;hpb=d4daee7b54e38e4b3d3d0a77759bddc1a4ede6e5;p=dbsrgits%2FDBIx-Class-Historic.git diff --git a/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm b/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm index 0925dec..26e3580 100644 --- a/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm +++ b/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm @@ -9,7 +9,7 @@ use namespace::clean -except => 'meta'; =head1 NAME -DBIx::Class::Storage::DBI::Replicated::Balancer - A Software Load Balancer +DBIx::Class::Storage::DBI::Replicated::Balancer - A Software Load Balancer =head1 SYNOPSIS @@ -27,9 +27,10 @@ This class defines the following attributes. =head2 auto_validate_every ($seconds) -If auto_validate has some sort of value, run the L every -$seconds. Be careful with this, because if you set it to 0 you will end up -validating every query. +If auto_validate has some sort of value, run +L +every $seconds. Be careful with this, because if you set it to 0 you +will end up validating every query. =cut @@ -70,12 +71,12 @@ has 'pool' => ( 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 +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 attribute has methods to help you shuffle through all the available replicants -via it's balancer object. +via its balancer object. =cut @@ -96,7 +97,7 @@ This class defines the following methods. =head2 _build_current_replicant -Lazy builder for the L attribute. +Lazy builder for the L attribute. =cut @@ -110,8 +111,8 @@ sub _build_current_replicant { This method should be defined in the class which consumes this role. Given a pool object, return the next replicant that will serve queries. The -default behavior is to grap the first replicant it finds but you can write -your own subclasses of L to +default behavior is to grab the first replicant it finds but you can write +your own subclasses of L to support other balance systems. This returns from the pool of active replicants. If there are no active @@ -123,27 +124,33 @@ Advice on next storage to add the autovalidation. We have this broken out so that it's easier to break out the auto validation into a role. This also returns the master in the case that none of the replicants are active -or just just forgot to create them :) +or just forgot to create them :) =cut +my $on_master; + around 'next_storage' => sub { my ($next_storage, $self, @args) = @_; my $now = time; ## Do we need to validate the replicants? if( - $self->has_auto_validate_every && + $self->has_auto_validate_every && ($self->auto_validate_every + $self->pool->last_validated) <= $now - ) { + ) { $self->pool->validate_replicants; } ## Get a replicant, or the master if none if(my $next = $self->$next_storage(@args)) { + $self->master->debugobj->print("Moved back to slave\n") if $on_master; + $on_master = 0; return $next; } else { - $self->master->debugobj->print("No Replicants validate, falling back to master reads. "); + $self->master->debugobj->print("No Replicants validate, falling back to master reads.\n") + unless $on_master++; + return $self->master; } }; @@ -173,7 +180,7 @@ around 'select' => sub { if (my $forced_pool = $args[-1]->{force_pool}) { delete $args[-1]->{force_pool}; - return $self->_get_forced_pool($forced_pool)->select(@args); + return $self->_get_forced_pool($forced_pool)->select(@args); } elsif($self->master->{transaction_depth}) { return $self->master->select(@args); } else { @@ -195,7 +202,7 @@ around 'select_single' => sub { if (my $forced_pool = $args[-1]->{force_pool}) { delete $args[-1]->{force_pool}; - return $self->_get_forced_pool($forced_pool)->select_single(@args); + return $self->_get_forced_pool($forced_pool)->select_single(@args); } elsif($self->master->{transaction_depth}) { return $self->master->select_single(@args); } else { @@ -232,17 +239,20 @@ sub _get_forced_pool { } elsif(my $replicant = $self->pool->replicants->{$forced_pool}) { return $replicant; } else { - $self->master->throw_exception("$forced_pool is not a named replicant."); - } + $self->master->throw_exception("'$forced_pool' is not a named replicant."); + } } -=head1 AUTHOR +=head1 FURTHER QUESTIONS? -John Napiorkowski +Check the list of L. -=head1 LICENSE +=head1 COPYRIGHT AND LICENSE -You may distribute this code under the same terms as Perl itself. +This module is free software L +by the L. You can +redistribute it and/or modify it under the same terms as the +L. =cut