DBIO
view release on metacpan or search on metacpan
lib/DBIO/AccessBroker.pm view on Meta::CPAN
}
return $self->_storage
? $self->connect_info_for_storage($self->_storage, $mode)
: $self->connect_info_for($mode);
}
# Pair this single credential identity with one host, returning a HostBound
# view. The view shares this broker's credentials and rotation lifecycle but
# reports the given host in its connect info, so one credential can serve many
# servers without this broker ever knowing the host list. Accepts a plain host
# string or a hashref ({ host => ..., port => ... }).
sub for_host {
my ($self, @args) = @_;
my %host_args =
@args == 1 && ref $args[0] eq 'HASH' ? %{ $args[0] }
: @args == 1 ? (host => $args[0])
: @args;
return DBIO::AccessBroker::HostBound->new(broker => $self, %host_args);
}
# Check refresh and return storage-native connect info.
sub current_connect_info_for_storage {
my ($self, $storage, $mode) = @_;
$mode //= 'write';
if ($self->needs_refresh) {
$self->refresh;
}
return $self->connect_info_for_storage($storage, $mode);
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
DBIO::AccessBroker - Credential lifecycle for DBIO connections
=head1 VERSION
version 0.900000
=head1 SYNOPSIS
# Static â same as traditional connect, one DSN
use DBIO::AccessBroker::Static;
my $broker = DBIO::AccessBroker::Static->new(
dsn => 'dbi:Pg:dbname=myapp',
username => 'app', password => 'secret',
);
# Storage gets storage-native connect info
my $info = $broker->current_connect_info_for_storage($schema->storage);
# Vault â rotating credentials from OpenBao/Vault
use DBIO::AccessBroker::Vault;
my $broker = DBIO::AccessBroker::Vault->new(
vault => WWW::OpenBao->new(endpoint => 'http://vault:8200', token => $token),
dsn => 'dbi:Pg:dbname=myapp;host=db',
cred_path => 'database/creds/myapp',
ttl => 3600, # credentials valid for 1 hour
refresh_margin => 900, # refresh 15 min before expiry
);
# DBIO can now connect directly with a broker
my $schema = MyApp::Schema->connect($broker);
=head1 DESCRIPTION
AccessBroker is a B<CredentialSource>: it supplies the connect info for
exactly one backend identity (one set of credentials). It is
B<storage-agnostic> â it returns connection parameters, not handles â
so it works with both C<Storage::DBI> (sync) and C<Storage::Async>
(async/Future-based). It handles:
=over 4
=item * B<Credential lifecycle> â fetching, rotating, and caching database credentials
=back
A broker does B<not> route, and it does B<not> own a host list. Read/write
routing and the master/replicant topology belong to L<DBIO::Replicated>. One
credential can serve many servers via a L</for_host> view, which pairs this
single identity with one host at connect time.
=head1 NAME
DBIO::AccessBroker - Credential lifecycle for DBIO connections
=head1 TRANSACTION SAFETY
A broker only supplies credentials, so the sole hazard to a running
transaction is credentials rotating mid-flight. DBIO distinguishes:
=over 4
=item * C<has_rotating_credentials()> â new connections may need refreshed credentials
=item * C<is_transaction_safe()> â DBIO may start a transaction through this broker without an explicit override
=back
The default implementation treats brokers as transaction-safe unless they
rotate credentials.
This means:
=over 4
=item * L<DBIO::AccessBroker::Static> is transaction-safe
=item * L<DBIO::AccessBroker::Vault> is not transaction-safe by default
=back
Starting a transaction through a broker marked as unsafe will throw by default.
If you intentionally want to allow this, set
C<DBIO_ALLOW_UNSAFE_BROKER_TRANSACTIONS=1>. DBIO will then proceed, but emit a
( run in 1.342 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )