NAME

DBIO::Storage::Composed - Runtime C3 composition of storage extension layers over a base storage class

VERSION

version 0.900001

DESCRIPTION

One behaviour, one transport. DBIO storage extensions ship as layers -- plain method packages that override or wrap the documented public storage surface -- and any number of them compose at runtime, over any base storage (the generic DBIO::Storage::DBI, a concrete driver storage, or a DBIO::Storage::Async transport), into a single synthesised class. There is no hand-written NxM matrix of extension-times-transport classes; the cell is built on demand here.

Composition is C3-MRO class synthesis -- the same mechanism family as load_components -- plus an explicit method-collision check. The synthesised class has no methods of its own: it is an empty package whose @ISA is (@layers, $base) under the c3 MRO, so method resolution walks the layers in registration order and falls through to the base. Layer hooks chain into the base (and into each other) with $self->next::method(@_).

Precedence

Registration order is C3 precedence: the first-registered layer is the most-specific rung of the synthesised @ISA, so its methods win the MRO and its next::method reaches the next layer, then the base. This is consistent with load_components: the component loaded first runs first.

Collision check

Silent shadowing between sibling layers is forbidden. If two or more layers each define their own copy of the same method name, "compose" croaks at compose time naming the method and every defining package. A single layer overriding a base method is fine (that is ordinary next::method layering); two layers overriding the same base method still croak -- the resolution between them would be an accident of registration order, never a decision.

Layer rules

A layer package:

  • MUST NOT use base a driver storage (it is mixed in above the base, not beside it);

  • is a plain method package -- no constructor, no @ISA pointing at a storage;

  • chains its hooks with $self->next::method(@_);

  • may only call the documented public storage surface.

METHODS

compose

my $class = DBIO::Storage::Composed->compose($base, \@layers);

Synthesise (or return the cached) storage class with @ISA = (@layers, $base) under the c3 MRO. The package name is deterministic -- DBIO::Storage::Composed::<layers>__<base> with :: flattened to _ -- so the same (base, layers) tuple always maps to the same class and is built at most once. With no layers the $base is returned unchanged (nothing to compose). Croaks (naming the method and the defining packages) if two or more layers define the same own method. Loads the base and every layer via "ensure_class_loaded" in Class::C3::Componentised; an unloadable one fails loud.

composition_of

my $entry = DBIO::Storage::Composed->composition_of($pkg);

Return the { base => $base, layers => \@layers } registry entry for a synthesised class, or undef when $pkg was not produced by "compose". This is how the rebless path ("_determine_driver" in DBIO::Storage::DBI) recognises a composed instance and recovers what it was composed from.

layers_of

my @layers = DBIO::Storage::Composed->layers_of($pkg);

The layer list a synthesised class was composed with, in registration order, or an empty list when $pkg is not a composed class.

recompose

my $new_class = DBIO::Storage::Composed->recompose($pkg, $new_base);

Re-run "compose" keeping $pkg's layer list but swapping in a different base. Used when a composed generic storage is reblessed onto its concrete driver class ("_determine_driver" in DBIO::Storage::DBI): the same layers must be re-composed over the driver, not dropped. Croaks if $pkg is not a composed class.

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.