DBIO
view release on metacpan or search on metacpan
t/composed/async_layer_core_read_capability.t view on Meta::CPAN
# ABSTRACT: an async layer that requires broker_connect_options -- a capability
# core reads, not layers -- over a transport with no query seam (karr k268)
#
# The layer gate in DBIO::Storage::DBI::_async_storage answers "does this
# transport offer what the layer needs" from transport_capabilities, all of
# them. One of those names is not about layers: broker_connect_options says the
# transport applies the connect options given beside an AccessBroker to every
# connection it opens, and core reads it for that (karr k243). It describes no
# query path. Since DBIO::Forked declares it (dbio-forked k12), a layer naming
# it as its requirement passes the gate on a Model A transport -- one that does
# not own the query path -- and composes over nothing it could wrap.
#
# k268 (decision 2026-10-09): core-read names are kept out of the layer gate.
# A layer requiring one is refused on every transport, Model A and B alike.
# No layer in the family asks for that name.
use strict;
use warnings;
use Test::More;
use DBIO::Test;
use DBIO::Test::Storage;
use DBIO::Storage::DBI;
use DBIO::Storage::Async;
use DBIO::Storage::Composed;
use DBIO::Future::Immediate;
# ---------------------------------------------------------------------------
# Transports. Model A is the DBIO::Forked shape: it overrides the *_async entry
# points and inherits the abstract _query_async stub -- no seam for a layer.
# ---------------------------------------------------------------------------
{
package T::K268::ModelA;
use base 'DBIO::Storage::Async';
use mro 'c3';
our @SELECTED;
sub future_class { 'DBIO::Future::Immediate' }
sub select_async { push @SELECTED, $_[1]; DBIO::Future::Immediate->done([ 1, 'row' ]) }
sub select_single_async { DBIO::Future::Immediate->done([]) }
sub insert_async { DBIO::Future::Immediate->done([]) }
sub update_async { DBIO::Future::Immediate->done(0) }
sub delete_async { DBIO::Future::Immediate->done(0) }
sub txn_do_async { DBIO::Future::Immediate->done(1) }
}
# Model A, taking connect options beside a broker: DBIO::Forked since k12.
{
package T::K268::ModelA::Declaring;
use base 'T::K268::ModelA';
use mro 'c3';
sub transport_capabilities { ('broker_connect_options') }
}
# Model B: owns the query path, and declares the same.
{
package T::K268::ModelB::Declaring;
use base 'DBIO::Storage::Async';
use mro 'c3';
sub future_class { 'DBIO::Future::Immediate' }
sub transport_capabilities { ('broker_connect_options') }
sub _query_async { DBIO::Future::Immediate->done([]) }
}
# ---------------------------------------------------------------------------
# Layers. "Asking" requires the core-read name and wraps the query seam, which
# is all an async layer can do; "Silent" declares nothing.
# ---------------------------------------------------------------------------
{ package T::K268::Asking; sub asking_sync { 1 } }
{
package T::K268::Asking::Async;
use mro 'c3';
our $WRAPPED = 0;
sub required_transport_capabilities { ('broker_connect_options') }
sub _query_async { my $self = shift; $WRAPPED++; return $self->next::method(@_) }
}
{ package T::K268::Silent; sub silent_sync { 1 } }
{ package T::K268::Silent::Async; sub silent_async { 1 } }
# Sanity: the transports differ in the property under test.
my $abstract_seam = DBIO::Storage::Async->can('_query_async');
is( T::K268::ModelA::Declaring->can('_query_async'), $abstract_seam,
'sanity: the Model A transport inherits the abstract stub -- no seam' );
isnt( T::K268::ModelB::Declaring->can('_query_async'), $abstract_seam,
'sanity: the Model B transport overrides the _query_async seam' );
# A fresh sync storage of $storage_class, bound to a live schema carrying
# @layers, in the 'ram' mode that class registered. The caller holds $schema.
sub build_storage {
my ($storage_class, @layers) = @_;
my $schema = DBIO::Test->init_schema;
$schema->register_storage_layer($_) for @layers;
my $storage = $storage_class->new($schema);
$storage->connect_info([ 'dbi:K268Mock:', '', '', { async => 'ram' } ]);
return ($storage, $schema);
}
{
package T::K268::A::Storage; use base 'DBIO::Test::Storage'; use mro 'c3';
package T::K268::AD::Storage; use base 'DBIO::Test::Storage'; use mro 'c3';
package T::K268::BD::Storage; use base 'DBIO::Test::Storage'; use mro 'c3';
( run in 0.637 second using v1.01-cache-2.11-cpan-145b269f2f3 )