5 use Data::Dump qw/dump/;
10 ? ( skip_all => 'needs DBD::Multi for testing' )
14 ## ----------------------------------------------------------------------------
15 ## Build a class to hold all our required testing data and methods.
16 ## ----------------------------------------------------------------------------
20 package DBIx::Class::DBI::Replication::TestReplication;
26 ## Create a constructor
33 db_paths => $params{db_paths},
34 dsns => $class->init_dsns(%params),
35 schema=>$class->init_schema,
42 ## get the DSNs. We build this up from the list of file paths
47 my $db_paths = $params{db_paths};
56 ## get the Schema and set the replication storage type
60 my $schema = DBICTest->init_schema();
61 $schema->storage_type( '::DBI::Replication' );
70 my ($master, @slaves) = @{$self->{dsns}};
71 my @connections = ([$master, '','', {AutoCommit=>1, PrintError=>0}]);
74 foreach my $slave (@slaves)
76 my $dbh = shift @{$self->{slaves}}
77 || DBI->connect($slave,"","",{PrintError=>0, PrintWarn=>0});
80 [$dbh, '','',{priority=>10}];
86 ## Keep track of the created slave databases
87 $self->{slaves} = \@slavesob;
93 {limit_dialect => 'LimitXY'}
101 my ($master, @slaves) = @{$self->{db_paths}};
103 foreach my $slave (@slaves) {
104 copy($master, $slave);
108 ## Cleanup afer ourselves.
112 my ($master, @slaves) = @{$self->{db_paths}};
114 foreach my $slave (@slaves) {
119 ## Force a reconnection
123 my $schema = $self->connect;
124 $self->{schema} = $schema;
129 ## ----------------------------------------------------------------------------
130 ## Create an object and run some tests
131 ## ----------------------------------------------------------------------------
135 "t/var/DBIxClass.db",
136 "t/var/DBIxClass_slave1.db",
137 "t/var/DBIxClass_slave2.db",
141 ok my $replicate = DBIx::Class::DBI::Replication::TestReplication->new(%params)
142 => 'Created a replication object';
144 isa_ok $replicate->{schema}
145 => 'DBIx::Class::Schema';
147 ## Add some info to the database
151 ->populate('Artist', [
152 [ qw/artistid name/ ],
153 [ 4, "Ozric Tentacles"],
156 ## Make sure all the slaves have the table definitions
158 $replicate->replicate;
160 ## Make sure we can read the data.
162 ok my $artist1 = $replicate->{schema}->resultset('Artist')->find(4)
166 => 'DBICTest::Artist';
168 is $artist1->name, 'Ozric Tentacles'
169 => 'Found expected name for first result';
171 ## Add some new rows that only the master will have This is because
172 ## we overload any type of write operation so that is must hit the master
175 use Fcntl qw (:flock);
177 my $master_path = $replicate->{db_paths}->[0];
178 open LOCKFILE, ">>$master_path"
179 or die "Cannot open $master_path";
180 flock(LOCKFILE, LOCK_EX);
184 ->populate('Artist', [
185 [ qw/artistid name/ ],
186 [ 5, "Doom's Children"],
187 [ 6, "Dead On Arrival"],
191 ## Reconnect the database
192 $replicate->reconnect;
194 ## Alright, the database 'cluster' is not in a consistent state. When we do
195 ## a read now we expect bad news
197 is $replicate->{schema}->resultset('Artist')->find(5), undef
198 => 'read after disconnect fails because it uses slave 1 which we have neglected to "replicate" yet';
200 ## Make sure all the slaves have the table definitions
201 $replicate->replicate;
203 ## Should find some data now
205 ok my $artist2 = $replicate->{schema}->resultset('Artist')->find(5)
209 => 'DBICTest::Artist';
211 is $artist2->name, "Doom's Children"
212 => 'Found expected name for first result';
214 ## What happens when we delete one of the slaves?
216 ok my $slave1 = @{$replicate->{slaves}}[0]
219 ok $slave1->disconnect
220 => 'disconnected slave1';
222 $replicate->reconnect;
224 ok my $artist3 = $replicate->{schema}->resultset('Artist')->find(6)
225 => 'Still finding stuff.';
228 => 'DBICTest::Artist';
230 is $artist3->name, "Dead On Arrival"
231 => 'Found expected name for first result';
233 ## Let's delete all the slaves
235 ok my $slave2 = @{$replicate->{slaves}}[1]
238 ok $slave2->disconnect
239 => 'Disconnected slave2';
241 $replicate->reconnect;
243 ## We expect an error now, since all the slaves are dead
246 $replicate->{schema}->resultset('Artist')->find(4)->name;
249 ok $@ => 'Got error when trying to find artistid 4';
251 ## This should also be an error
254 my $artist4 = $replicate->{schema}->resultset('Artist')->find(7);
257 ok $@ => 'Got read errors after everything failed';
259 ## Delete the old database files