NAME
DBIO::AccessBroker::HostBound - One credential identity pinned to one host
VERSION
version 0.900004
SYNOPSIS
my $broker = DBIO::AccessBroker::Vault->new(...); # one Vault lease
my $primary = $broker->for_host('db-primary');
my $replica = $broker->for_host({ host => 'db-replica', port => 5433 });
# $primary and $replica share one credential lease; only the host differs.
See t/access_broker/06-replicated-passthrough.t for a runnable example.
DESCRIPTION
A HostBound view pairs one CredentialSource (a wrapped DBIO::AccessBroker) with one host. It is how a single credential can serve many servers: the application builds one view per server with $broker->for_host($host) and hands each to the connection on that host -- the master's connect, a replicant's entry in "connect_replicants" in DBIO::Replicated::Storage as [ $view ]. DBIO::Replicated passes the views through; it does not build them, and the broker itself never learns the host list.
The view holds no credentials of its own. Every credential operation — needs_refresh, refresh, has_rotating_credentials, is_transaction_safe — delegates to the wrapped broker, so all views built from one broker share a single lease and a single rotation schedule. The view adds exactly one thing: it injects its host (and optional port) into the connect info the broker returns, handling both the hashref form ({host,port,dbname,...}) and the DBI-arrayref/DSN form, the latter through the driver seam "_bind_host_into_dsn" in DBIO::Storage::DBI.
METHODS
new
my $view = DBIO::AccessBroker::HostBound->new(
broker => $broker, # required, a DBIO::AccessBroker
host => 'db-replica', # required
port => 5433, # optional
);
Builds a host-bound view over broker. Croaks if broker is missing or not a DBIO::AccessBroker instance, or if host is missing. Normally not called directly -- use "for_host" in DBIO::AccessBroker.
underlying_broker
Returns the wrapped DBIO::AccessBroker -- the real CredentialSource behind this view. Two views sharing one lease return the same broker here.
host
Returns the host this view is pinned to.
port
Returns the port this view is pinned to, or undef when none was given (the wrapped broker's port, if any, is then passed through unchanged).
needs_refresh
refresh
has_rotating_credentials
is_transaction_safe
All four delegate to the wrapped broker unchanged: every view built from one broker shares a single lease and a single rotation schedule. See "TRANSACTION SAFETY" in DBIO::AccessBroker.
set_storage
$view->set_storage($storage);
Attaches the view to $storage (via "set_storage" in DBIO::AccessBroker) and also attaches the wrapped broker, so storage-aware credential lookups and storage-tied rotation keep working. The storage is added to what the wrapped broker is attached to: several views over one broker, each given its own storage, leave the wrapped broker attached to all of them. Returns the view.
unset_storage
$view->unset_storage($storage);
Detaches the view from $storage and the wrapped broker from it as well ("unset_storage" in DBIO::AccessBroker). Only that storage: the others the wrapped broker is attached to through other views stay. Returns the storage.
connect_info_for
my $info = $view->connect_info_for($mode);
Asks the wrapped broker for its connect info and injects this view's host (and port, if set). Handles both shapes a broker may return: the hashref form ({host, port, dbname, ...}, whose host/port keys are overwritten) and the DBI-arrayref form ([$dsn, $user, $pass, \%attrs], whose DSN gets its host=/port= tokens rewritten or inserted after dbi:Driver:). Any other shape is returned untouched.
How a DSN names its server is the DBD's business, so a DSN string is not rewritten by the view itself: it asks the storage's driver seam "_bind_host_into_dsn" in DBIO::Storage::DBI (ADR 0013, addendum 2026-10-09). The candidates are the class of the storage, when one is given, and the storage class registered for the DBD named in the DSN ("register_driver" in DBIO::Storage::DBI) -- a storage is still the generic class before its first connection; the first whose seam is not core's default answers. Core's default translates the host=/port= form and declines the rest. A driver that names its server another way overrides the seam in its storage class.
What nobody can translate is refused, never passed on: the connection dies with a message naming the form (a key, a dialect) -- never the DSN, never a credential -- because a replicant given the view would otherwise connect to the host the answer named. That covers a DSN naming its server another way that no driver seam translates (Oracle Easy Connect or a TNS descriptor, DB2's HOSTNAME=, Sybase's server=, an ODBC data source, hostaddr=); an array starting with a code reference, and a hash carrying a dbh_maker, whose code opens the connection with no DSN for the view to rewrite; and a view's host or port containing ;, which would add tokens to a DSN -- that is refused before any seam is asked, so no driver ever sees it. A hash carrying a dsn has the host and port bound into that DSN the same way and gets no host/port keys. Where the view was not given a storage ("connect_info_for") the core default is the only candidate besides the registry.
An answer that is nothing -- undef, an empty hash or array, a false value -- is handed on as it came: an empty hash does not become { host => ..., port => ... }. The storage then refuses it, naming the wrapped broker that answered nothing and this view ("current_access_broker_connect_info" in DBIO::Storage).
connect_info_for_storage
my $info = $view->connect_info_for_storage($storage, $mode);
Storage-aware variant of "connect_info_for": calls the wrapped broker's connect_info_for_storage and injects the host the same way.
AUTHOR
DBIO & DBIx::Class Authors
COPYRIGHT AND LICENSE
Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.