MooseX::AttributeHelpers => '0.12',
MooseX::Types => '0.10',
namespace::clean => '0.11',
+ Hash::Merge => '0.11'
);
my @didnt_load;
use MooseX::Types::Moose qw/ClassName HashRef Object/;
use Scalar::Util 'reftype';
use Carp::Clan qw/^DBIx::Class/;
+use Hash::Merge 'merge';
use namespace::clean -except => 'meta';
MooseX::AttributeHelpers => 0.12
MooseX::Types => 0.10
namespace::clean => 0.11
+ Hash::Merge => 0.11
You will need to install these modules manually via CPAN or make them part of the
Makefile for your distribution.
=cut
has 'pool_type' => (
- is=>'ro',
+ is=>'rw',
isa=>ClassName,
- required=>1,
default=>'DBIx::Class::Storage::DBI::Replicated::Pool',
handles=>{
'create_pool' => 'new',
=cut
has 'pool_args' => (
- is=>'ro',
+ is=>'rw',
isa=>HashRef,
lazy=>1,
- required=>1,
default=>sub { {} },
);
=cut
has 'balancer_type' => (
- is=>'ro',
+ is=>'rw',
isa=>BalancerClassNamePart,
coerce=>1,
required=>1,
=cut
has 'balancer_args' => (
- is=>'ro',
+ is=>'rw',
isa=>HashRef,
lazy=>1,
required=>1,
=cut
has 'balancer' => (
- is=>'ro',
+ is=>'rw',
isa=>'DBIx::Class::Storage::DBI::Replicated::Balancer',
lazy_build=>1,
handles=>[qw/auto_validate_every/],
is=>'ro',
isa=>Object,
lazy_build=>1,
- lazy_build=>1,
handles=>[qw/
on_connect_do
on_disconnect_do
=head2 around: connect_info
Preserve master's C<connect_info> options (for merging with replicants.)
+Also set any Replicated related options from connect_info, such as
+C<pool_type>, C<pool_args>, C<balancer_type> and C<balancer_args>.
=cut
around connect_info => sub {
my ($next, $self, $info, @extra) = @_;
+ my $wantarray = wantarray;
+
my %opts;
for my $arg (@$info) {
next unless (reftype($arg)||'') eq 'HASH';
- %opts = (%opts, %$arg);
+ %opts = %{ merge($arg, \%opts) };
}
-
delete $opts{dsn};
+ if (@opts{qw/pool_type pool_args/}) {
+ $self->pool_type(delete $opts{pool_type})
+ if $opts{pool_type};
+
+ $self->pool_args(
+ merge((delete $opts{pool_args} || {}), $self->pool_args)
+ );
+
+ $self->pool($self->_build_pool)
+ if $self->pool;
+ }
+
+ if (@opts{qw/balancer_type balancer_args/}) {
+ $self->balancer_type(delete $opts{balancer_type})
+ if $opts{balancer_type};
+
+ $self->balancer_args(
+ merge((delete $opts{balancer_args} || {}), $self->balancer_args)
+ );
+
+ $self->balancer($self->_build_balancer)
+ if $self->balancer;
+ }
+
$self->_master_connect_info_opts(\%opts);
- $self->$next($info, @extra);
+ my (@res, $res);
+ if ($wantarray) {
+ @res = $self->$next($info, @extra);
+ } else {
+ $res = $self->$next($info, @extra);
+ }
+
+ # Make sure master is blessed into the correct class and apply role to it.
+ my $master = $self->master;
+ $master->_determine_driver;
+ Moose::Meta::Class->initialize(ref $master);
+ DBIx::Class::Storage::DBI::Replicated::WithDSN->meta->apply($master);
+
+ $wantarray ? @res : $res;
};
=head1 METHODS
sub _build_master {
my $self = shift @_;
- DBIx::Class::Storage::DBI->new($self->schema);
+ my $master = DBIx::Class::Storage::DBI->new($self->schema);
+ $master
}
=head2 _build_pool
$r->[$i] = {} unless $r->[$i];
# merge if two hashes
- my %opts = map %$_, @$r[$i .. $#{$r}];
+ my @hashes = @$r[$i .. $#{$r}];
+
+ croak "invalid connect_info options"
+ if (grep { reftype($_) eq 'HASH' } @hashes) != @hashes;
+
+ croak "too many hashrefs in connect_info"
+ if @hashes > 2;
+
+ my %opts = %{ merge(reverse @hashes) };
+
+# delete them
splice @$r, $i+1, ($#{$r} - $i), ();
# merge with master
- %opts = (%{ $self->_master_connect_info_opts }, %opts);
+ %opts = %{ merge(\%opts, $self->_master_connect_info_opts) };
# update
$r->[$i] = \%opts;