[Bast-commits] r4359 - in DBIx-Class/0.08/branches/replication_dedux: lib/DBIx/Class lib/DBIx/Class/Storage lib/DBIx/Class/Storage/DBI lib/DBIx/Class/Storage/DBI/Replicated lib/DBIx/Class/Storage/DBI/Replicated/Balancer t t/lib

jnapiorkowski at dev.catalyst.perl.org jnapiorkowski at dev.catalyst.perl.org
Wed May 7 23:40:30 BST 2008


Author: jnapiorkowski
Date: 2008-05-07 23:40:30 +0100 (Wed, 07 May 2008)
New Revision: 4359

Modified:
   DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Schema.pm
   DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI.pm
   DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated.pm
   DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm
   DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer/Random.pm
   DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/mysql.pm
   DBIx-Class/0.08/branches/replication_dedux/t/93storage_replication.t
   DBIx-Class/0.08/branches/replication_dedux/t/lib/DBICTest.pm
Log:
changed the way args are passed to a storage, should make it easier to use existing code using this, added the master as a fallback to the the replicants, lots of small documentation updates and test improvements.  all tests passing

Modified: DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Schema.pm
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Schema.pm	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Schema.pm	2008-05-07 22:40:30 UTC (rev 4359)
@@ -14,7 +14,6 @@
 __PACKAGE__->mk_classdata('class_mappings' => {});
 __PACKAGE__->mk_classdata('source_registrations' => {});
 __PACKAGE__->mk_classdata('storage_type' => '::DBI');
-__PACKAGE__->mk_classdata('storage_type_args' => {});
 __PACKAGE__->mk_classdata('storage');
 __PACKAGE__->mk_classdata('exception_action');
 __PACKAGE__->mk_classdata('stacktrace' => $ENV{DBIC_TRACE} || 0);
@@ -638,9 +637,9 @@
 
 =over 4
 
-=item Arguments: $storage_type
+=item Arguments: $storage_type|[$storage_type, \%args]
 
-=item Return Value: $storage_type
+=item Return Value: $storage_type|[$storage_type, \%args]
 
 =back
 
@@ -654,6 +653,11 @@
 dealing with MSSQL via L<DBD::Sybase>, in which case you'd set it to
 C<::DBI::Sybase::MSSQL>.
 
+If your storage type requires instantiation arguments, those are defined as a 
+second argument in the form of a hashref and the entire value needs to be
+wrapped into an arrayref.  See L<DBIx::Class::Storage::DBI::Replicated> for an
+example of this.
+
 =head2 connection
 
 =over 4
@@ -676,14 +680,17 @@
 sub connection {
   my ($self, @info) = @_;
   return $self if !@info && $self->storage;
-  my $storage_class = $self->storage_type;
+  
+  my ($storage_class, $args) = ref $self->storage_type ? 
+    (@{$self->storage_type},{}) : ($self->storage_type, {});
+    
   $storage_class = 'DBIx::Class::Storage'.$storage_class
     if $storage_class =~ m/^::/;
   eval "require ${storage_class};";
   $self->throw_exception(
     "No arguments to load_classes and couldn't load ${storage_class} ($@)"
   ) if $@;
-  my $storage = $storage_class->new($self, $self->storage_type_args);
+  my $storage = $storage_class->new($self=>$args);
   $storage->connect_info(\@info);
   $self->storage($storage);
   return $self;

Modified: DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer/Random.pm
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer/Random.pm	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer/Random.pm	2008-05-07 22:40:30 UTC (rev 4359)
@@ -40,12 +40,11 @@
 =cut
 
 sub next_storage {
-	my $self = shift @_;
-	return (shuffle($self->pool->active_replicants))[0]
-	  if $self->pool->active_replicants;
+    my $self = shift @_;
+    my $next = (shuffle($self->pool->active_replicants))[0];
+    return $next ? $next : $self->master;
 }
 
-
 =head1 AUTHOR
 
 John Napiorkowski <john.napiorkowski at takkle.com>

Modified: DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated/Balancer.pm	2008-05-07 22:40:30 UTC (rev 4359)
@@ -21,6 +21,20 @@
 
 This class defines the following attributes.
 
+=head2 master
+
+The L<DBIx::Class::Storage::DBI> object that is the master database all the
+replicants are trying to follow.  The balancer needs to know it since it's the
+ultimate fallback.
+
+=cut
+
+has 'master' => (
+    is=>'ro',
+    isa=>'DBIx::Class::Storage::DBI',
+    required=>1,
+);
+
 =head2 pool
 
 The L<DBIx::Class::Storage::DBI::Replicated::Pool> object that we are trying to
@@ -70,7 +84,7 @@
 
 sub _build_current_replicant {
     my $self = shift @_;
-    $self->next_storage($self->pool);
+    $self->next_storage;
 }
 
 =head2 next_storage
@@ -80,15 +94,18 @@
 your own subclasses of L<DBIx::Class::Storage::DBI::Replicated::Balancer> to 
 support other balance systems.
 
+This returns from the pool of active replicants.  If there are no active
+replicants, then you should have it return the master as an ultimate fallback.
+
 =cut
 
 sub next_storage {
 	my $self = shift @_;
-	return ($self->pool->active_replicants)[0]
-	  if $self->pool->active_replicants;
+	my $next = ($self->pool->active_replicants)[0];
+	return $next ? $next:$self->master;
 }
 
-=head2 after: select
+=head2 before: 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
@@ -96,13 +113,13 @@
 
 =cut
 
-after 'select' => sub {
+before 'select' => sub {
     my $self = shift @_;
     my $next_replicant = $self->next_storage;
     $self->current_replicant($next_replicant);
 };
 
-=head2 after: select_single
+=head2 before: 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
@@ -110,13 +127,13 @@
 
 =cut
 
-after 'select_single' => sub {
+before 'select_single' => sub {
     my $self = shift @_;
     my $next_replicant = $self->next_storage;
     $self->current_replicant($next_replicant);
 };
 
-=head2 after: columns_info_for
+=head2 before: 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
@@ -124,7 +141,7 @@
 
 =cut
 
-after 'columns_info_for' => sub {
+before 'columns_info_for' => sub {
     my $self = shift @_;
     my $next_replicant = $self->next_storage;
     $self->current_replicant($next_replicant);

Modified: DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated.pm
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated.pm	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/Replicated.pm	2008-05-07 22:40:30 UTC (rev 4359)
@@ -19,7 +19,7 @@
 tasks.
 
     ## Change storage_type in your schema class
-    $schema->storage_type( '::DBI::Replicated' );
+    $schema->storage_type( ['::DBI::Replicated', {balancer=>'::Random'}] );
     
     ## Add some slaves.  Basically this is an array of arrayrefs, where each
     ## arrayref is database connect information
@@ -67,15 +67,12 @@
 has 'pool_type' => (
     is=>'ro',
     isa=>'ClassName',
-    required=>1,
-    lazy=>1,
-    default=>'DBIx::Class::Storage::DBI::Replicated::Pool',
+    lazy_build=>1,
     handles=>{
     	'create_pool' => 'new',
     },
 );
 
-
 =head2 balancer_type
 
 The replication pool requires a balance class to provider the methods for
@@ -86,15 +83,12 @@
 has 'balancer_type' => (
     is=>'ro',
     isa=>'ClassName',
-    required=>1,
-    lazy=>1,
-    default=>'DBIx::Class::Storage::DBI::Replicated::Balancer',
+    lazy_build=>1,
     handles=>{
     	'create_balancer' => 'new',
     },
 );
 
-
 =head2 pool
 
 Is a <DBIx::Class::Storage::DBI::Replicated::Pool> or derived class.  This is a
@@ -115,7 +109,6 @@
     /],
 );
 
-
 =head2 balancer
 
 Is a <DBIx::Class::Storage::DBI::Replicated::Balancer> or derived class.  This 
@@ -129,7 +122,6 @@
     lazy_build=>1,
 );
 
-
 =head2 master
 
 The master defines the canonical state for a pool of connected databases.  All
@@ -146,7 +138,6 @@
     lazy_build=>1,
 );
 
-
 =head1 ATTRIBUTES IMPLEMENTING THE DBIx::Storage::DBI INTERFACE
 
 The following methods are delegated all the methods required for the 
@@ -169,7 +160,6 @@
     /],    
 );
 
-
 =head2 write_handler
 
 Defines an object that implements the write side of L<BIx::Class::Storage::DBI>.
@@ -207,7 +197,6 @@
     /],
 );
 
-
 =head1 METHODS
 
 This class defines the following methods.
@@ -227,7 +216,14 @@
     my $schema = shift @_;
     my $storage_type_args = shift @_;
     my $obj = $class->SUPER::new($schema, $storage_type_args, @_);
-  
+    
+    ## Hate to do it this way, but can't seem to get advice on the attribute working right
+    ## maybe we can do a type and coercion for it. 
+    if( $storage_type_args->{balancer_type} && $storage_type_args->{balancer_type}=~m/^::/) {
+    	$storage_type_args->{balancer_type} = 'DBIx::Class::Storage::DBI::Replicated::Balancer'.$storage_type_args->{balancer_type};
+    	eval "require $storage_type_args->{balancer_type}";
+    }
+    
     return $class->meta->new_object(
         __INSTANCE__ => $obj,
         %$storage_type_args,
@@ -245,6 +241,16 @@
 	DBIx::Class::Storage::DBI->new;
 }
 
+=head2 _build_pool_type
+
+Lazy builder for the L</pool_type> attribute.
+
+=cut
+
+sub _build_pool_type {
+    return 'DBIx::Class::Storage::DBI::Replicated::Pool';
+}
+
 =head2 _build_pool
 
 Lazy builder for the L</pool> attribute.
@@ -255,6 +261,16 @@
     shift->create_pool;
 }
 
+=head2 _build_balancer_type
+
+Lazy builder for the L</balancer_type> attribute.
+
+=cut
+
+sub _build_balancer_type {
+    return 'DBIx::Class::Storage::DBI::Replicated::Balancer';
+}
+
 =head2 _build_balancer
 
 Lazy builder for the L</balancer> attribute.  This takes a Pool object so that
@@ -264,7 +280,9 @@
 
 sub _build_balancer {
     my $self = shift @_;
-    $self->create_balancer(pool=>$self->pool);
+    $self->create_balancer(
+        pool=>$self->pool, 
+        master=>$self->master);
 }
 
 =head2 _build_write_handler

Modified: DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/mysql.pm
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/mysql.pm	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI/mysql.pm	2008-05-07 22:40:30 UTC (rev 4359)
@@ -34,6 +34,14 @@
     $self->dbh->do("ROLLBACK TO SAVEPOINT $name")
 }
 
+sub is_replicating {
+    my $self = shift @_;
+}
+
+sub lag_behind_master {
+    my $self = shift @_;
+}
+
 1;
 
 =head1 NAME

Modified: DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI.pm
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI.pm	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/lib/DBIx/Class/Storage/DBI.pm	2008-05-07 22:40:30 UTC (rev 4359)
@@ -1708,6 +1708,31 @@
     }
 }
 
+=head2 is_replicating
+
+A boolean that reports if a particular L<DBIx::Class::Storage::DBI> is set to
+replicate from a master database.  Default is undef, which is the result
+returned by databases that don't support replication.
+
+=cut
+
+sub is_replicating {
+    return;
+    
+}
+
+=head2 lag_behind_master
+
+Returns a number that represents a certain amount of lag behind a master db
+when a given storage is replicating.  The number is database dependent, but
+starts at zero and increases with the amount of lag. Default in undef
+
+=cut
+
+sub lag_behind_master {
+    return;
+}
+
 sub DESTROY {
   my $self = shift;
   return if !$self->_dbh;

Modified: DBIx-Class/0.08/branches/replication_dedux/t/93storage_replication.t
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/t/93storage_replication.t	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/t/93storage_replication.t	2008-05-07 22:40:30 UTC (rev 4359)
@@ -13,7 +13,6 @@
 
 use_ok 'DBIx::Class::Storage::DBI::Replicated::Pool';
 use_ok 'DBIx::Class::Storage::DBI::Replicated::Balancer';
-use_ok 'DBIx::Class::Storage::DBI::Replicated::Balancer::Random';
 use_ok 'DBIx::Class::Storage::DBI::Replicated::Replicant';
 use_ok 'DBIx::Class::Storage::DBI::Replicated';
 
@@ -49,10 +48,11 @@
     sub init_schema {
         my $class = shift @_;
         my $schema = DBICTest->init_schema(
-            storage_type=>'::DBI::Replicated', 
-            storage_type_args=>{
-            	balancer_type=>'DBIx::Class::Storage::DBI::Replicated::Balancer::Random',
-            });
+            storage_type=>[
+            	'::DBI::Replicated' => {
+            		balancer_type=>'::Random',
+            	}],
+            );
 
         return $schema;
     }
@@ -320,8 +320,16 @@
     
 ok $replicated->schema->resultset('Artist')->find(2)
     => 'back to replicant 2.';
+
+## set all the replicants to inactive, and make sure the balancer falls back to
+## the master.
+
+$replicated->schema->storage->replicants->{"t/var/DBIxClass_slave1.db"}->active(0);
+$replicated->schema->storage->replicants->{"t/var/DBIxClass_slave2.db"}->active(0);
     
-
+ok $replicated->schema->resultset('Artist')->find(2)
+    => 'Fallback to master'; 
+       
 ## Delete the old database files
 $replicated->cleanup;
 

Modified: DBIx-Class/0.08/branches/replication_dedux/t/lib/DBICTest.pm
===================================================================
--- DBIx-Class/0.08/branches/replication_dedux/t/lib/DBICTest.pm	2008-05-07 21:16:22 UTC (rev 4358)
+++ DBIx-Class/0.08/branches/replication_dedux/t/lib/DBICTest.pm	2008-05-07 22:40:30 UTC (rev 4359)
@@ -84,9 +84,6 @@
     } else {
       $schema = DBICTest::Schema->compose_namespace('DBICTest');
     }
-    if( $args{storage_type_args}) {
-    	$schema->storage_type_args($args{storage_type_args});
-    } 
     if( $args{storage_type}) {
     	$schema->storage_type($args{storage_type});
     }    
@@ -115,9 +112,9 @@
 
 sub deploy_schema {
     my $self = shift;
-    my $schema = shift;
+    my $schema = shift; 
 
-    if ($ENV{"DBICTEST_SQLT_DEPLOY"}) {
+    if ($ENV{"DBICTEST_SQLT_DEPLOY"}) { 
         return $schema->deploy();
     } else {
         open IN, "t/lib/sqlite.sql";




More information about the Bast-commits mailing list