Commit | Line | Data |
26ab719a |
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::Replicated::Replicant', |
40 | handles=>{ |
41 | 'create_replicant' => 'new', |
42 | }, |
43 | ); |
44 | |
26ab719a |
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::Replicated::Replicant]', |
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 | |
26ab719a |
98 | =head1 METHODS |
99 | |
100 | This class defines the following methods. |
101 | |
955a6df6 |
102 | =head2 connect_replicants ($schema, Array[$connect_info]) |
26ab719a |
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 | |
955a6df6 |
110 | sub connect_replicants { |
26ab719a |
111 | my $self = shift @_; |
50336325 |
112 | my $schema = shift @_; |
26ab719a |
113 | |
114 | my @newly_created = (); |
115 | foreach my $connect_info (@_) { |
50336325 |
116 | my $replicant = $self->create_replicant($schema); |
26ab719a |
117 | $replicant->connect_info($connect_info); |
118 | $replicant->ensure_connected; |
119 | my ($key) = ($connect_info->[0]=~m/^dbi\:.+\:(.+)$/); |
120 | $self->set_replicant( $key => $replicant); |
121 | push @newly_created, $replicant; |
122 | } |
123 | |
124 | return @newly_created; |
125 | } |
126 | |
26ab719a |
127 | =head2 connected_replicants |
128 | |
129 | Returns true if there are connected replicants. Actually is overloaded to |
130 | return the number of replicants. So you can do stuff like: |
131 | |
132 | if( my $num_connected = $storage->has_connected_replicants ) { |
133 | print "I have $num_connected connected replicants"; |
134 | } else { |
135 | print "Sorry, no replicants."; |
136 | } |
137 | |
138 | This method will actually test that each replicant in the L</replicants> hashref |
139 | is actually connected, try not to hit this 10 times a second. |
140 | |
141 | =cut |
142 | |
143 | sub connected_replicants { |
144 | my $self = shift @_; |
145 | return sum( map { |
146 | $_->connected ? 1:0 |
147 | } $self->all_replicants ); |
148 | } |
149 | |
50336325 |
150 | =head2 active_replicants |
151 | |
152 | This is an array of replicants that are considered to be active in the pool. |
153 | This does not check to see if they are connected, but if they are not, DBIC |
154 | should automatically reconnect them for us when we hit them with a query. |
155 | |
156 | =cut |
157 | |
158 | sub active_replicants { |
159 | my $self = shift @_; |
160 | return ( grep {$_} map { |
161 | $_->active ? $_:0 |
162 | } $self->all_replicants ); |
163 | } |
164 | |
26ab719a |
165 | =head2 all_replicants |
166 | |
167 | Just a simple array of all the replicant storages. No particular order to the |
168 | array is given, nor should any meaning be derived. |
169 | |
170 | =cut |
171 | |
172 | sub all_replicants { |
173 | my $self = shift @_; |
174 | return values %{$self->replicants}; |
175 | } |
176 | |
26ab719a |
177 | =head1 AUTHOR |
178 | |
179 | John Napiorkowski <john.napiorkowski@takkle.com> |
180 | |
181 | =head1 LICENSE |
182 | |
183 | You may distribute this code under the same terms as Perl itself. |
184 | |
185 | =cut |
186 | |
cb6ec758 |
187 | 1; |