refactored the duties of the different balancer classes, added tests and docs
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Replicated / Balancer.pm
CommitLineData
26ab719a 1package DBIx::Class::Storage::DBI::Replicated::Balancer;
2
3use Moose;
26ab719a 4
5=head1 NAME
6
7DBIx::Class::Storage::DBI::Replicated::Balancer; A Software Load Balancer
8
9=head1 SYNOPSIS
10
11This class is used internally by L<DBIx::Class::Storage::DBI::Replicated>. You
12shouldn't need to create instances of this class.
13
14=head1 DESCRIPTION
15
16Given a pool (L<DBIx::Class::Storage::DBI::Replicated::Pool>) of replicated
17database's (L<DBIx::Class::Storage::DBI::Replicated::Replicant>), defines a
18method by which query load can be spread out across each replicant in the pool.
19
20=head1 ATTRIBUTES
21
22This class defines the following attributes.
23
cb6ec758 24=head2 pool
25
26The L<DBIx::Class::Storage::DBI::Replicated::Pool> object that we are trying to
27balance.
28
29=cut
30
31has 'pool' => (
32 is=>'ro',
33 isa=>'DBIx::Class::Storage::DBI::Replicated::Pool',
34 required=>1,
35);
36
37=head2 current_replicant
38
39Replicant storages (slaves) handle all read only traffic. The assumption is
40that your database will become readbound well before it becomes write bound
41and that being able to spread your read only traffic around to multiple
42databases is going to help you to scale traffic.
43
44This attribute returns the next slave to handle a read request. Your L</pool>
45attribute has methods to help you shuffle through all the available replicants
46via it's balancer object.
47
48=cut
49
50has 'current_replicant' => (
51 is=> 'rw',
52 isa=>'DBIx::Class::Storage::DBI',
53 lazy_build=>1,
54 handles=>[qw/
55 select
56 select_single
57 columns_info_for
58 /],
59);
60
26ab719a 61=head1 METHODS
62
63This class defines the following methods.
64
cb6ec758 65=head2 _build_current_replicant
66
67Lazy builder for the L</current_replicant_storage> attribute.
68
69=cut
70
71sub _build_current_replicant {
72 my $self = shift @_;
73 $self->next_storage($self->pool);
74}
75
76=head2 next_storage
26ab719a 77
78Given a pool object, return the next replicant that will serve queries. The
cb6ec758 79default behavior is to grap the first replicant it finds but you can write
80your own subclasses of L<DBIx::Class::Storage::DBI::Replicated::Balancer> to
81support other balance systems.
26ab719a 82
83=cut
84
85sub next_storage {
86 my $self = shift @_;
cb6ec758 87 return ($self->pool->active_replicants)[0]
88 if $self->pool->active_replicants;
26ab719a 89}
90
cb6ec758 91=head2 after: select
92
93Advice on the select attribute. Each time we use a replicant
94we need to change it via the storage pool algorithm. That way we are spreading
95the load evenly (hopefully) across existing capacity.
96
97=cut
98
99after 'select' => sub {
100 my $self = shift @_;
101 my $next_replicant = $self->next_storage;
102 $self->current_replicant($next_replicant);
103};
104
105=head2 after: select_single
106
107Advice on the select_single attribute. Each time we use a replicant
108we need to change it via the storage pool algorithm. That way we are spreading
109the load evenly (hopefully) across existing capacity.
110
111=cut
112
113after 'select_single' => sub {
114 my $self = shift @_;
115 my $next_replicant = $self->next_storage;
116 $self->current_replicant($next_replicant);
117};
118
119=head2 after: columns_info_for
120
121Advice on the current_replicant_storage attribute. Each time we use a replicant
122we need to change it via the storage pool algorithm. That way we are spreading
123the load evenly (hopefully) across existing capacity.
124
125=cut
126
127after 'columns_info_for' => sub {
128 my $self = shift @_;
129 my $next_replicant = $self->next_storage;
130 $self->current_replicant($next_replicant);
131};
26ab719a 132
133=head1 AUTHOR
134
135John Napiorkowski <john.napiorkowski@takkle.com>
136
137=head1 LICENSE
138
139You may distribute this code under the same terms as Perl itself.
140
141=cut
142
cb6ec758 1431;