changed the way args are passed to a storage, should make it easier to use existing...
[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
106d5f3b 24=head2 master
25
26The L<DBIx::Class::Storage::DBI> object that is the master database all the
27replicants are trying to follow. The balancer needs to know it since it's the
28ultimate fallback.
29
30=cut
31
32has 'master' => (
33 is=>'ro',
34 isa=>'DBIx::Class::Storage::DBI',
35 required=>1,
36);
37
cb6ec758 38=head2 pool
39
40The L<DBIx::Class::Storage::DBI::Replicated::Pool> object that we are trying to
41balance.
42
43=cut
44
45has 'pool' => (
46 is=>'ro',
47 isa=>'DBIx::Class::Storage::DBI::Replicated::Pool',
48 required=>1,
49);
50
51=head2 current_replicant
52
53Replicant storages (slaves) handle all read only traffic. The assumption is
54that your database will become readbound well before it becomes write bound
55and that being able to spread your read only traffic around to multiple
56databases is going to help you to scale traffic.
57
58This attribute returns the next slave to handle a read request. Your L</pool>
59attribute has methods to help you shuffle through all the available replicants
60via it's balancer object.
61
62=cut
63
64has 'current_replicant' => (
65 is=> 'rw',
66 isa=>'DBIx::Class::Storage::DBI',
67 lazy_build=>1,
68 handles=>[qw/
69 select
70 select_single
71 columns_info_for
72 /],
73);
74
26ab719a 75=head1 METHODS
76
77This class defines the following methods.
78
cb6ec758 79=head2 _build_current_replicant
80
81Lazy builder for the L</current_replicant_storage> attribute.
82
83=cut
84
85sub _build_current_replicant {
86 my $self = shift @_;
106d5f3b 87 $self->next_storage;
cb6ec758 88}
89
90=head2 next_storage
26ab719a 91
92Given a pool object, return the next replicant that will serve queries. The
cb6ec758 93default behavior is to grap the first replicant it finds but you can write
94your own subclasses of L<DBIx::Class::Storage::DBI::Replicated::Balancer> to
95support other balance systems.
26ab719a 96
106d5f3b 97This returns from the pool of active replicants. If there are no active
98replicants, then you should have it return the master as an ultimate fallback.
99
26ab719a 100=cut
101
102sub next_storage {
103 my $self = shift @_;
106d5f3b 104 my $next = ($self->pool->active_replicants)[0];
105 return $next ? $next:$self->master;
26ab719a 106}
107
106d5f3b 108=head2 before: select
cb6ec758 109
110Advice on the select attribute. Each time we use a replicant
111we need to change it via the storage pool algorithm. That way we are spreading
112the load evenly (hopefully) across existing capacity.
113
114=cut
115
106d5f3b 116before 'select' => sub {
cb6ec758 117 my $self = shift @_;
118 my $next_replicant = $self->next_storage;
119 $self->current_replicant($next_replicant);
120};
121
106d5f3b 122=head2 before: select_single
cb6ec758 123
124Advice on the select_single attribute. Each time we use a replicant
125we need to change it via the storage pool algorithm. That way we are spreading
126the load evenly (hopefully) across existing capacity.
127
128=cut
129
106d5f3b 130before 'select_single' => sub {
cb6ec758 131 my $self = shift @_;
132 my $next_replicant = $self->next_storage;
133 $self->current_replicant($next_replicant);
134};
135
106d5f3b 136=head2 before: columns_info_for
cb6ec758 137
138Advice on the current_replicant_storage attribute. Each time we use a replicant
139we need to change it via the storage pool algorithm. That way we are spreading
140the load evenly (hopefully) across existing capacity.
141
142=cut
143
106d5f3b 144before 'columns_info_for' => sub {
cb6ec758 145 my $self = shift @_;
146 my $next_replicant = $self->next_storage;
147 $self->current_replicant($next_replicant);
148};
26ab719a 149
150=head1 AUTHOR
151
152John Napiorkowski <john.napiorkowski@takkle.com>
153
154=head1 LICENSE
155
156You may distribute this code under the same terms as Perl itself.
157
158=cut
159
cb6ec758 1601;