Introducing DBIx::Class::Schema::SanityChecker
This gives us comprehensive diagnostic on incorrect component composition
and other hard to track... stuff.
Given the huge amount of changes to call chains (specifically the changes
in
77c3a5dc and e5053694), and the fallout seen on CPAN and darkpan due to
these modifications, the status quo became clearly untennable. To mitigate
the (often silent) breakage a brand new "sanity check" framework was
introduced as part of the ::Schema setup-cycle (and is enabled by default)
Same DBIx::Class::Helper v2.032002 test time shoots from 65.5s all the way
to 76.0s, a 16% slowdown. However the moment the framework is disabled by
flipping $schema->schema_sanity_checker to a defined-but-false value - the
startup impact is entirely gone.
The changset was extensively tested against the following set of downstream
dists (a superset of
c8b1011e), with each warning hand-confirmed to be a
valid description of a real problem:
--- actual bash script passing on a *heavily* massaged PERL5LIB
set -o pipefail
export PERL_CPANM_OPT=
export PERL5LIB="/home/rabbit/devel/dbic/dbgit/lib:$PERL5LIB"
export DBICTEST_SQLT_DEPLOY=0
export DBIC_ASSERT_NO_ERRONEOUS_METAINSTANCE_USE=1
export DBIC_ASSERT_NO_FAILING_SANITY_CHECKS=1
# these fail with ERRONEOUS_METAINSTANCE_USE alone
# (S::L fails due to PG_DSN but I think is ok besides that)
for d in \
DBICx::Shortcuts \
DBIx::Class::Bootstrap::Simple \
DBIx::Class::Preview \
DBIx::Class::Schema::Loader \
Pinto \
; do \
DBIC_ASSERT_NO_ERRONEOUS_METAINSTANCE_USE=0 \
DBIC_ASSERT_NO_FAILING_SANITY_CHECKS=0 \
DBICTEST_PG_DSN= \
cpanm -v --reinstall $d 2>&1 \
| tee -a /dev/shm/umpfh \
| grep -P -B1 'sanity check|emit_|^(Building and testing|Result:)' || exit 1 \
; done
# these emit various san-check related problems
for d in \
RapidApp \
Data::OFAC \
DBIx::Class::VirtualColumns \
"DBD::SQLite@1.35 Handel" \
DBIx::Class::RDBOHelpers \
CatalystX::CRUD::ModelAdapter::DBIC \
DBICx::Indexing \
DBICx::TestDatabase \
DBIx::Class::BitField \
DBIx::Class::I18NColumns \
DBIx::Class::PhoneticSearch \
DBIx::Class::RandomColumns \
DBIx::Class::ResultSource::MultipleTableInheritance \
DBIx::Class::Result::ProxyField \
DBIx::Class::Schema::PopulateMore \
DBIx::Class::Tree \
Foorum \
Interchange6::Schema \
Test::DBIx::Class \
TreePath \
; do \
DBIC_ASSERT_NO_FAILING_SANITY_CHECKS=0 \
cpanm -v --reinstall $d 2>&1 \
| tee -a /dev/shm/umpfh \
| grep -P -B1 'sanity check|emit_|^(Building and testing|Result:)' || exit 1 \
; done
# these are entirely unaffected \o/
for d in \
Dancer2::Plugin::DBIC \
App::DBCritic \
App::DH \
AproJo \
Articulate \
Authorization::RBAC \
BackPAN::Index \
Bio::Chado::Schema \
Bot::BasicBot::Pluggable::Module::Notes \
Bracket \
Business::Cart::Generic \
Business::DPD \
Catalyst::Authentication::Credential::Facebook \
Catalyst::Authentication::Store::DBIx::Class \
Catalyst::Controller::DBIC::API \
Catalyst::Model::DBIC::Plain \
Catalyst::Model::DBIC::Schema \
Catalyst::Model::DBIC::Schema::PerRequest \
Catalyst::Model::FormFu \
Catalyst::Plugin::Authentication::Store::DBIC \
Catalyst::Plugin::Authorization::Abilities \
Catalyst::Plugin::AutoCRUD \
Catalyst::Plugin::DBIC::Schema::Profiler \
Catalyst::Plugin::Session::Store::DBIC \
Catalyst::TraitFor::Controller::DBIC::DoesPaging \
Catalyst::TraitFor::Model::DBIC::Schema::RequestConnectionPool \
Catalyst::TraitFor::Model::DBIC::Schema::Result \
Catalyst::TraitFor::Model::DBIC::Schema::WithCurrentUser \
Catalyst::View::CSV \
CatalystX::Controller::ExtJS::REST::SimpleExcel \
CatalystX::Crudite \
CatalystX::Eta \
CatalystX::OAuth2 \
CatalystX::Resource \
CGI::Application::Plugin::Authentication::Driver::DBIC \
CGI::Application::Plugin::DBIC::Schema \
CGI::Application::Plugin::DBIx::Class \
CGI::Application::Plugin::ExtJS \
CGI::Session::Driver::dbic \
Cookieville \
Dancer2::Plugin::Auth::Extensible::Provider::DBIC \
Dancer2::Session::DBIC \
Dancer::Plugin::Auth::Extensible::Provider::DBIC \
Dancer::Plugin::Auth::RBAC::Credentials::DBIC \
Dancer::Plugin::Auth::RBAC::Permissions::DBIC \
Dancer::Plugin::DBIC \
Dancer::Session::DBIC \
Data::Morph \
DBICx::AutoDoc \
DBICx::Backend::Move \
DBICx::DataDictionary \
DBICx::Deploy \
DBICx::Hooks \
DBICx::MapMaker \
DBICx::MaterializedPath \
DBICx::Modeler \
DBICx::Sugar \
DBICx::TxnInsert \
DBIx::Class::AlwaysUpdate \
DBIx::Class::AuditAny \
DBIx::Class::AuditLog \
DBIx::Class::BatchUpdate \
DBIx::Class::Candy \
DBIx::Class::ColumnDefault \
DBIx::Class::CompressColumns \
DBIx::Class::Cursor::Cached \
DBIx::Class::CustomPrefetch \
DBIx::Class::DateTime::Epoch \
DBIx::Class::DeleteAction \
DBIx::Class::DeploymentHandler \
DBIx::Class::DigestColumns \
DBIx::Class::DynamicDefault \
DBIx::Class::DynamicSubclass \
DBIx::Class::EasyFixture \
DBIx::Class::ElasticSync \
DBIx::Class::EncodeColumns \
DBIx::Class::EncodedColumn \
DBIx::Class::Factory \
DBIx::Class::Fixtures \
DBIx::Class::ForceUTF8 \
DBIx::Class::FormatColumns \
DBIx::Class::FormTools \
DBIx::Class::FromSledge \
DBIx::Class::FrozenColumns \
DBIx::Class::GeomColumns \
DBIx::Class::Graph \
DBIx::Class::Helpers \
DBIx::Class::HTML::FormFu \
DBIx::Class::HTMLWidget \
DBIx::Class::Indexed \
DBIx::Class::InflateColumn::Authen::Passphrase \
DBIx::Class::InflateColumn::BigFloat \
DBIx::Class::InflateColumn::Boolean \
DBIx::Class::InflateColumn::Currency \
DBIx::Class::InflateColumn::DateTime::Duration \
DBIx::Class::InflateColumn::DateTime::WithTimeZone \
DBIx::Class::InflateColumn::DateTimeX::Immutable \
DBIx::Class::InflateColumn::FS \
DBIx::Class::InflateColumn::IP \
DBIx::Class::InflateColumn::Markup::Unified \
DBIx::Class::InflateColumn::Math::Currency \
DBIx::Class::InflateColumn::Object::Enum \
DBIx::Class::InflateColumn::Path::Class \
DBIx::Class::InflateColumn::Serializer \
DBIx::Class::InflateColumn::Serializer::JSYNC \
DBIx::Class::InflateColumn::Serializer::Role::HashContentAccessor \
DBIx::Class::InflateColumn::Serializer::Sereal \
DBIx::Class::InflateColumn::Time \
DBIx::Class::InflateColumn::TimeMoment \
DBIx::Class::InflateColumn::URI \
DBIx::Class::IntrospectableM2M \
DBIx::Class::Journal \
DBIx::Class::LibXMLdoc \
DBIx::Class::LookupColumn \
DBIx::Class::MaterializedPath \
DBIx::Class::Migration \
DBIx::Class::Numeric \
DBIx::Class::Objects \
DBIx::Class::OptimisticLocking \
DBIx::Class::ParameterizedJoinHack \
DBIx::Class::PassphraseColumn \
DBIx::Class::QueriesTime \
DBIx::Class::QueryLog \
DBIx::Class::QueryLog::WithStackTrace \
DBIx::Class::QueryProfiler \
DBIx::Class::RandomStringColumns \
DBIx::Class::Relationship::Predicate \
DBIx::Class::Report \
DBIx::Class::Result::ColumnData \
DBIx::Class::ResultSet::AccessorsEverywhere \
DBIx::Class::ResultSet::Data::Pageset \
DBIx::Class::ResultSet::Excel \
DBIx::Class::ResultSet::Faceter \
DBIx::Class::ResultSet::HashRef \
DBIx::Class::ResultSet::RecursiveUpdate \
DBIx::Class::Result::Validation \
DBIx::Class::SaltedPasswords \
DBIx::Class::Schema::Config \
DBIx::Class::Schema::Diff \
DBIx::Class::Schema::RestrictWithObject \
DBIx::Class::Schema::ResultSetAccessors \
DBIx::Class::Schema::Versioned::Inline \
DBIx::Class::Service \
DBIx::Class::SingletonRows \
DBIx::Class::Storage::DBI::mysql::backup \
DBIx::Class::Storage::DBI::ODBC::OPENEDGE \
DBIx::Class::Storage::DBI::OpenEdge \
DBIx::Class::StorageReadOnly \
DBIx::Class::Storage::TxnEndHook \
DBIx::Class::TimeStamp \
DBIx::Class::Tokenize \
DBIx::Class::TopoSort \
DBIx::Class::Tree::CalculateSets \
DBIx::Class::Tree::Mobius \
DBIx::Class::UnicornLogger \
DBIx::Class::UserStamp \
DBIx::Class::UUIDColumns \
DBIx::Class::Validation \
DBIx::Class::Validation::Structure \
DBIx::Class::WebForm \
DBIx::Class::Wrapper \
DBIx::Table::TestDataGenerator \
Data::Importer \
Dwimmer \
ETLp \
ExtJS::Generator::DBIC \
Finance::QuoteDB \
Form::Processor::Model::DBIC \
Form::Sensible::Reflector::DBIC \
FormValidator::Simple::Plugin::DBIC::Unique \
Galileo \
GenOO \
HTML::FormFu::ExtJS \
HTML::FormFu::Model::DBIC \
HTML::FormHandler::Model::DBIC \
Hyle \
IronMan::Schema \
KiokuDB::Backend::DBI \
Log::Log4perl::Appender::DBIx::Class \
Mixin::ExtraFields::Driver::DBIC \
Module::CPANTS::ProcessCPAN \
Mojolicious::Plugin::DBICAdmin \
MooseX::Types::DBIx::Class \
OpusVL::AppKit \
OpusVL::AppKit::Schema::AppKitAuthDB \
OpusVL::Preferences \
OpusVL::SysParams \
Prosody \
Pulp \
RackMan \
Reaction \
Schema::RackTables \
Tapper::MCP \
Tapper::Schema \
Template::Provider::CustomDBIC \
Template::Provider::DBIC \
Template::Provider::PerContextDBIC \
Template::Provider::PrefixDBIC \
Test::DBIC::ExpectedQueries \
Test::DBIC::Schema::Connector \
Test::DBIx::Class::Schema \
Test::Fixture::DBIC::Schema \
Tie::DBIx::Class \
Types::DBIx::Class \
WebAPI::DBIC \
WebNano::Controller::CRUD \
Web::Util::DBIC::Paging \
Web::Util::ExtPaging \
WWW::Hashbang::Pastebin \
WWW::RobotRules::DBIC \
YAWF \
YATT::Lite \
Yeb::Plugin::DBIC \
"DBD::SQLite@1.35 Catalyst::ActionRole::BuildDBICResult DBIx::NoSQL Jedi::Plugin::Session Jedi::Plugin::Auth" \
"Test::More@1.001014 Test::DBIx::Class::Stats" \
"Mojolicious@3.91 ExpenseTracker" \
"Dancer2@0.166001 Strehler Strehler::Element::Extra Strehler::RSS" \
; do \
cpanm -v --reinstall $d 2>&1 \
| tee -a /dev/shm/umpfh \
| grep -P -B1 '^(Building and testing|Result:)' || exit 1 \
; done
echo
echo 'YAY!'
exit 0