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 )