9 ? ( skip_all => 'needs DBD::Multi for testing' )
13 ## ----------------------------------------------------------------------------
14 ## Build a class to hold all our required testing data and methods.
15 ## ----------------------------------------------------------------------------
19 package DBIx::Class::DBI::Replication::TestReplication;
25 ## Create a constructor
32 db_paths => $params{db_paths},
33 dsns => $class->init_dsns(%params),
34 schema=>$class->init_schema,
41 ## get the DSNs. We build this up from the list of file paths
46 my $db_paths = $params{db_paths};
55 ## get the Schema and set the replication storage type
59 my $schema = DBICTest->init_schema();
60 $schema->storage_type( '::DBI::Replication' );
69 my ($master, @slaves) = @{$self->{dsns}};
70 my @connections = ([$master, '','', {AutoCommit=>1, PrintError=>0}]);
73 foreach my $slave (@slaves)
75 my $dbh = shift @{$self->{slaves}}
76 || DBI->connect($slave,"","",{PrintError=>0, PrintWarn=>0});
79 [$dbh, '','',{priority=>10}];
85 ## Keep track of the created slave databases
86 $self->{slaves} = \@slavesob;
92 {limit_dialect => 'LimitXY'}
100 my ($master, @slaves) = @{$self->{db_paths}};
102 foreach my $slave (@slaves) {
103 copy($master, $slave);
107 ## Cleanup afer ourselves.
111 my ($master, @slaves) = @{$self->{db_paths}};
113 foreach my $slave (@slaves) {
118 ## Force a reconnection
122 my $schema = $self->connect;
123 $self->{schema} = $schema;
128 ## ----------------------------------------------------------------------------
129 ## Create an object and run some tests
130 ## ----------------------------------------------------------------------------
134 "t/var/DBIxClass.db",
135 "t/var/DBIxClass_slave1.db",
136 "t/var/DBIxClass_slave2.db",
140 ok my $replicate = DBIx::Class::DBI::Replication::TestReplication->new(%params)
141 => 'Created a replication object';
143 isa_ok $replicate->{schema}
144 => 'DBIx::Class::Schema';
146 ## Add some info to the database
150 ->populate('Artist', [
151 [ qw/artistid name/ ],
152 [ 4, "Ozric Tentacles"],
155 ## Make sure all the slaves have the table definitions
157 $replicate->replicate;
159 ## Make sure we can read the data.
161 ok my $artist1 = $replicate->{schema}->resultset('Artist')->find(4)
165 => 'DBICTest::Artist';
167 is $artist1->name, 'Ozric Tentacles'
168 => 'Found expected name for first result';
170 ## Add some new rows that only the master will have This is because
171 ## we overload any type of write operation so that is must hit the master
174 use Fcntl qw (:flock);
176 my $master_path = $replicate->{db_paths}->[0];
177 open LOCKFILE, ">>$master_path"
178 or die "Cannot open $master_path";
179 flock(LOCKFILE, LOCK_EX);
183 ->populate('Artist', [
184 [ qw/artistid name/ ],
185 [ 5, "Doom's Children"],
186 [ 6, "Dead On Arrival"],
190 ## Reconnect the database
191 $replicate->reconnect;
193 ## Alright, the database 'cluster' is not in a consistent state. When we do
194 ## a read now we expect bad news
196 is $replicate->{schema}->resultset('Artist')->find(5), undef
197 => 'read after disconnect fails because it uses slave 1 which we have neglected to "replicate" yet';
199 ## Make sure all the slaves have the table definitions
200 $replicate->replicate;
202 ## Should find some data now
204 ok my $artist2 = $replicate->{schema}->resultset('Artist')->find(5)
208 => 'DBICTest::Artist';
210 is $artist2->name, "Doom's Children"
211 => 'Found expected name for first result';
213 ## What happens when we delete one of the slaves?
215 ok my $slave1 = @{$replicate->{slaves}}[0]
218 ok $slave1->disconnect
219 => 'disconnected slave1';
221 $replicate->reconnect;
223 ok my $artist3 = $replicate->{schema}->resultset('Artist')->find(6)
224 => 'Still finding stuff.';
227 => 'DBICTest::Artist';
229 is $artist3->name, "Dead On Arrival"
230 => 'Found expected name for first result';
232 ## Let's delete all the slaves
234 ok my $slave2 = @{$replicate->{slaves}}[1]
237 ok $slave2->disconnect
238 => 'Disconnected slave2';
240 $replicate->reconnect;
242 ## We expect an error now, since all the slaves are dead
245 $replicate->{schema}->resultset('Artist')->find(4)->name;
248 ok $@ => 'Got error when trying to find artistid 4';
250 ## This should also be an error
253 my $artist4 = $replicate->{schema}->resultset('Artist')->find(7);
256 ok $@ => 'Got read errors after everything failed';
258 ## Delete the old database files