Comprehensive diagnostic on incorrect ResultSource metadata use
authorPeter Rabbitson <ribasushi@cpan.org>
Fri, 22 Apr 2016 10:39:00 +0000 (12:39 +0200)
committerPeter Rabbitson <ribasushi@cpan.org>
Tue, 26 Jul 2016 09:00:44 +0000 (11:00 +0200)
commit73f54e275e7dc98b4a082475ff252afdbeca182f
treebc2e0be266abdecce163a5cbaceac49fc1c2bd86
parente570488ade8f327f47dd3318db3443a348d561d6
Comprehensive diagnostic on incorrect ResultSource metadata use

This commit is the second part of the permanent RT#107462 solution f064a2ab.
Given the amount of changes to the resultsource metadata subsystem, I can
not be certain that everything has been accounted for, even despite the
comprehensive assertion harness added in the previous commits passing with
flying colors on the entire reverse dep list detailed in c8b1011e.

As Dave Howorth correctly pointed out in [1], the diagnostic of why something
stopped working within the metadata subsystem is pretty daunting, especially
given the ass-backward nature of DBIC's implementation of it. The (minimal
but present) performance hit is deemed worth it in order to be able to
present this information to downstream. One unexpected bit of good news is
that none of the downstreams tested emitted the warning, which is an extra
point of confidence that the main change of f064a2ab, and the even more
dangerous change in 9e36e3ec are both solid.

The gist here is that this:

~/devel/dbic$ perl -Ilib -It/lib -MDBICTest -e '
  my $art = DBICTest->init_schema->resultset("Artist")->find(1);

  DBICTest::Schema::Artist->add_column("foo");

  DBICTest::Schema->source("Artist")->add_columns("foo");

  $art->has_column("foo");
'

now emits a comprehensive non-trappable warning along the lines of:

DBIx::Class::ResultSource::Table=HASH(0x2a32660) (the metadata instance
of source 'Artist') is *OUTDATED*, and does not reflect the modifications
of its *ancestors* as follows:
  * DBIx::Class::ResultSource::Table=HASH(0x24ed770)->add_column(...) at -e line 4
  * DBIx::Class::ResultSource::Table=HASH(0x2955da8)->add_columns(...) at -e line 6
Stale metadata accessed by 'getter' DBIx::Class::ResultSource::Table=HASH(0x2a32660)->has_column(...)
  within the callstack beginning at lib/DBIx/Class/ResultSource.pm line 231.
DBIx::Class::ResultSource::get_rsrc_instance_specific_attribute(DBIx::Class::ResultSource::Table=HASH(0x2a32660), "_columns") called at (eval 95) line 2
DBIx::Class::ResultSource::_columns(DBIx::Class::ResultSource::Table=HASH(0x2a32660)) called at lib/DBIx/Class/ResultSource.pm line 732
DBIx::Class::ResultSource::has_column(DBIx::Class::ResultSource::Table=HASH(0x2a32660), "foo") called at (eval 70) line 19
DBIx::Class::ResultSourceProxy::has_column(DBICTest::Artist=HASH(0x311e338), "foo") called at -e line 8

The performance hit consistently measures in the ~1.5% range: the test suite
of @frioux's DBIx::Class::Helpers v2.032002 consistently completes within
roughly ~63.7 CPU seconds at the base of this branch, yet climbs to ~64.6 as
of this commit (on an idle low-clocked Xeon L3426)

The warning can not be disabled for the time being (aside from monkeypatching
DBIC::ResultSource) - the wide-range testing indicates it only fires on real
legitimate problems. Hopefully I am making the right call...

[1] http://lists.scsys.co.uk/pipermail/dbix-class/2016-January/012127.html
Changes
lib/DBIx/Class/Carp.pm
lib/DBIx/Class/ResultSource.pm
lib/DBIx/Class/ResultSource/View.pm
lib/DBIx/Class/ResultSourceHandle.pm
lib/DBIx/Class/ResultSourceProxy/Table.pm
lib/DBIx/Class/_Util.pm
xt/dist/pod_coverage.t
xt/extra/diagnostics/divergent_metadata.t [new file with mode: 0644]