1d65b853515c94e7235cf428f56f14682b81f614
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Replicated / Pool.pm
1 package DBIx::Class::Storage::DBI::Replicated::Pool;
2
3 use Moose;
4 use MooseX::AttributeHelpers;
5 use DBIx::Class::Storage::DBI::Replicated::Replicant;
6 use List::Util qw(sum);
7
8 =head1 NAME
9
10 DBIx::Class::Storage::DBI::Replicated::Pool; Manage a pool of replicants
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 In a replicated storage type, there is at least one replicant to handle the
20 read only traffic.  The Pool class manages this replicant, or list of 
21 replicants, and gives some methods for querying information about their status.
22
23 =head1 ATTRIBUTES
24
25 This class defines the following attributes.
26
27 =head2 replicant_type
28
29 Base class used to instantiate replicants that are in the pool.  Unless you
30 need to subclass L<DBIx::Class::Storage::DBI::Replicated::Replicant> you should
31 just leave this alone.
32
33 =cut
34
35 has 'replicant_type' => (
36     is=>'ro',
37     isa=>'ClassName',
38     required=>1,
39     default=>'DBIx::Class::Storage::DBI',
40     handles=>{
41         'create_replicant' => 'new',
42     },  
43 );
44
45 =head2 replicants
46
47 A hashref of replicant, with the key being the dsn and the value returning the
48 actual replicant storage.  For example if the $dsn element is something like:
49
50     "dbi:SQLite:dbname=dbfile"
51     
52 You could access the specific replicant via:
53
54     $schema->storage->replicants->{'dbname=dbfile'}
55     
56 This attributes also supports the following helper methods
57
58 =over 4
59
60 =item set_replicant($key=>$storage)
61
62 Pushes a replicant onto the HashRef under $key
63
64 =item get_replicant($key)
65
66 Retrieves the named replicant
67
68 =item has_replicants
69
70 Returns true if the Pool defines replicants.
71
72 =item num_replicants
73
74 The number of replicants in the pool
75
76 =item delete_replicant ($key)
77
78 removes the replicant under $key from the pool
79
80 =back
81
82 =cut
83
84 has 'replicants' => (
85     is=>'rw',
86     metaclass => 'Collection::Hash',
87     isa=>'HashRef[DBIx::Class::Storage::DBI]',
88     default=>sub {{}},
89     provides  => {
90                 'set' => 'set_replicant',
91                 'get' => 'get_replicant',            
92                 'empty' => 'has_replicants',
93                 'count' => 'num_replicants',
94                 'delete' => 'delete_replicant',
95         },
96 );
97
98 =head1 METHODS
99
100 This class defines the following methods.
101
102 =head2 connect_replicants ($schema, Array[$connect_info])
103
104 Given an array of $dsn suitable for connected to a database, create an
105 L<DBIx::Class::Storage::DBI::Replicated::Replicant> object and store it in the
106 L</replicants> attribute.
107
108 =cut
109
110 use Data::Dump qw/dump/; 
111
112 sub connect_replicants {
113         my $self = shift @_;
114         my $schema = shift @_;
115         
116         my @newly_created = ();
117         foreach my $connect_info (@_) {
118                 
119                 my $replicant = $self->create_replicant($schema);
120                 $replicant->connect_info($connect_info);        
121                 $replicant->ensure_connected;
122                 DBIx::Class::Storage::DBI::Replicated::Replicant->meta->apply($replicant);
123                 
124                 my ($key) = ($connect_info->[0]=~m/^dbi\:.+\:(.+)$/);
125                 $self->set_replicant( $key => $replicant);      
126                 push @newly_created, $replicant;
127         }
128         
129         return @newly_created;
130 }
131
132 =head2 connected_replicants
133
134 Returns true if there are connected replicants.  Actually is overloaded to
135 return the number of replicants.  So you can do stuff like:
136
137     if( my $num_connected = $storage->has_connected_replicants ) {
138         print "I have $num_connected connected replicants";
139     } else {
140         print "Sorry, no replicants.";
141     }
142
143 This method will actually test that each replicant in the L</replicants> hashref
144 is actually connected, try not to hit this 10 times a second.
145
146 =cut
147
148 sub connected_replicants {
149         my $self = shift @_;
150         return sum( map {
151                 $_->connected ? 1:0
152         } $self->all_replicants );
153 }
154
155 =head2 active_replicants
156
157 This is an array of replicants that are considered to be active in the pool.
158 This does not check to see if they are connected, but if they are not, DBIC
159 should automatically reconnect them for us when we hit them with a query.
160
161 =cut
162
163 sub active_replicants {
164     my $self = shift @_;
165     return ( grep {$_} map {
166         $_->active ? $_:0
167     } $self->all_replicants );
168 }
169
170 =head2 all_replicants
171
172 Just a simple array of all the replicant storages.  No particular order to the
173 array is given, nor should any meaning be derived.
174
175 =cut
176
177 sub all_replicants {
178         my $self = shift @_;
179         return values %{$self->replicants};
180 }
181
182 =head1 AUTHOR
183
184 John Napiorkowski <john.napiorkowski@takkle.com>
185
186 =head1 LICENSE
187
188 You may distribute this code under the same terms as Perl itself.
189
190 =cut
191
192 1;