::DBI::Replicated - fix fallback to master, test for the warning, other cleanups
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Replicated / Balancer / Random.pm
1 package DBIx::Class::Storage::DBI::Replicated::Balancer::Random;
2
3 use Moose;
4 with 'DBIx::Class::Storage::DBI::Replicated::Balancer';
5 use DBIx::Class::Storage::DBI::Replicated::Types 'Weight';
6 use namespace::clean -except => 'meta';
7
8 =head1 NAME
9
10 DBIx::Class::Storage::DBI::Replicated::Balancer::Random - A 'random' Balancer
11
12 =head1 SYNOPSIS
13
14 This class is used internally by L<DBIx::Class::Storage::DBI::Replicated>.  You
15 shouldn't need to create instances of this class.
16     
17 =head1 DESCRIPTION
18
19 Given a pool (L<DBIx::Class::Storage::DBI::Replicated::Pool>) of replicated
20 database's (L<DBIx::Class::Storage::DBI::Replicated::Replicant>), defines a
21 method by which query load can be spread out across each replicant in the pool.
22
23 This Balancer uses L<List::Util> keyword 'shuffle' to randomly pick an active
24 replicant from the associated pool.  This may or may not be random enough for
25 you, patches welcome.
26
27 =head1 ATTRIBUTES
28
29 This class defines the following attributes.
30
31 =head2 master_read_weight
32
33 A number from 0 to 1 that specifies what weight to give the master when choosing
34 which backend to execute a read query on. A value of 0, which is the default,
35 does no reads from master, while a value of 1 gives it the same priority as any
36 single replicant.
37
38 =cut
39
40 has master_read_weight => (is => 'rw', isa => Weight, default => sub { 0 });
41
42 =head1 METHODS
43
44 This class defines the following methods.
45
46 =head2 next_storage
47
48 Returns an active replicant at random.  Please note that due to the nature of
49 the word 'random' this means it's possible for a particular active replicant to
50 be requested several times in a row.
51
52 =cut
53
54 sub next_storage {
55   my $self = shift @_;
56
57   my @replicants = $self->pool->active_replicants;
58
59   if (not @replicants) {
60     # will fall back to master anyway
61     return;
62   }
63
64   my $master     = $self->master;
65
66   my $rnd = $self->_random_number(@replicants + $self->master_read_weight);
67
68   return $rnd >= @replicants ? $master : $replicants[int $rnd];
69 }
70
71 sub _random_number {
72   rand($_[1])
73 }
74
75 =head1 AUTHOR
76
77 John Napiorkowski <john.napiorkowski@takkle.com>
78
79 =head1 LICENSE
80
81 You may distribute this code under the same terms as Perl itself.
82
83 =cut
84
85 __PACKAGE__->meta->make_immutable;
86
87 1;