DBIC and Moo woes

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

DBIC and Moo woes

Aran Deltac-2
I've been converting a lot of @work's custom components, result, result set, schema, and storage classes (yes, we even have custom storage classes) to Moo roles and classes.

I've just about completed it and have worked through a lot of issues, but am left with one remaining issue which I'm stumped at and have been able to whittle it down to a couple small examples:

package FooResult;
use Moo;
print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') . "\n";
extends 'DBIx::Class::Core';
print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') . "\n";

That prints:
HAS BUILDARGS: YES
HAS BUILDARGS: NO

I was able to change this to YES-YES by adding Moo::Object to the front of my extends, which in the above example would look like:

extends 'Moo::Object', 'DBIx::Class::Core';

Is that the right thing to do when inheriting from a non-Moo class?  Documentation on non-moo inheritance was minimal in the Moo docs, but maybe I missed it.  Note that I found this issue via a Moose result class which inherits from my Moo result base class which inherits from DBIx::Class::Core.  Something about that relationship structure requires BUILDARGS even though the involved code neither declares nor calls BUILDARGS.

Another issue is this:

package FooResult;
use Moo;
extends 'DBIx::Class::Core';
has bar => ( is=>'ro' );
FooResult->new( bar=>32 );

Which then hangs with:

Deep recursion on subroutine "DBIx::Class::Row::throw_exception" at /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1416.
Deep recursion on subroutine "DBIx::Class::Row::result_source" at /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1568.

I tried fiddling with FOREIGNBUILDARGS to see if I could produce arguments which made DBIC's new() happy but it was a fruitless effort.

At this point the error I am getting with the real application code is:

DBIx::Class::Sims::load_sims(): Can't call method "new" on an undefined value at /home/aran/local-lib/lib/perl5/DBIx/Class/ResultSet.pm line 2590. at /home/aran/ziprecruiter/app/t/lib/Test/ZR/Schema.pm line 95

Which is what lead me to the two previous examples.  As far as I can tell my Moo conversion is complete and there is something wrong with the argument processing between Moo and DBIC.

I'm using the latest DBIC (0.082800) and Moo (1.006).

Any pointers, examples, words of wisdom, RTFMs, etc, appreciated.

Thanks!

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: DBIC and Moo woes

Aran Deltac-2
I've abstracted out my work to something more general.  I'm going to copy over and run the entire DBIC test suite against it and see what fails.  There is some magic in the load_components bit as it uses some Moo internals to do the Moo extends and with properly.  Just posting here if anyone is curious.


Aran

On Wed, Oct 1, 2014 at 7:21 PM, Aran Deltac <[hidden email]> wrote:
I've been converting a lot of @work's custom components, result, result set, schema, and storage classes (yes, we even have custom storage classes) to Moo roles and classes.

I've just about completed it and have worked through a lot of issues, but am left with one remaining issue which I'm stumped at and have been able to whittle it down to a couple small examples:

package FooResult;
use Moo;
print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') . "\n";
extends 'DBIx::Class::Core';
print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') . "\n";

That prints:
HAS BUILDARGS: YES
HAS BUILDARGS: NO

I was able to change this to YES-YES by adding Moo::Object to the front of my extends, which in the above example would look like:

extends 'Moo::Object', 'DBIx::Class::Core';

Is that the right thing to do when inheriting from a non-Moo class?  Documentation on non-moo inheritance was minimal in the Moo docs, but maybe I missed it.  Note that I found this issue via a Moose result class which inherits from my Moo result base class which inherits from DBIx::Class::Core.  Something about that relationship structure requires BUILDARGS even though the involved code neither declares nor calls BUILDARGS.

Another issue is this:

package FooResult;
use Moo;
extends 'DBIx::Class::Core';
has bar => ( is=>'ro' );
FooResult->new( bar=>32 );

Which then hangs with:

Deep recursion on subroutine "DBIx::Class::Row::throw_exception" at /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1416.
Deep recursion on subroutine "DBIx::Class::Row::result_source" at /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1568.

I tried fiddling with FOREIGNBUILDARGS to see if I could produce arguments which made DBIC's new() happy but it was a fruitless effort.

At this point the error I am getting with the real application code is:

DBIx::Class::Sims::load_sims(): Can't call method "new" on an undefined value at /home/aran/local-lib/lib/perl5/DBIx/Class/ResultSet.pm line 2590. at /home/aran/ziprecruiter/app/t/lib/Test/ZR/Schema.pm line 95

Which is what lead me to the two previous examples.  As far as I can tell my Moo conversion is complete and there is something wrong with the argument processing between Moo and DBIC.

I'm using the latest DBIC (0.082800) and Moo (1.006).

Any pointers, examples, words of wisdom, RTFMs, etc, appreciated.

Thanks!


_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: DBIC and Moo woes

Graham Knop
In reply to this post by Aran Deltac-2
On Wed, Oct 1, 2014 at 10:21 PM, Aran Deltac <[hidden email]> wrote:

> I've been converting a lot of @work's custom components, result, result set,
> schema, and storage classes (yes, we even have custom storage classes) to
> Moo roles and classes.
>
> I've just about completed it and have worked through a lot of issues, but am
> left with one remaining issue which I'm stumped at and have been able to
> whittle it down to a couple small examples:
>
> package FooResult;
> use Moo;
> print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') .
> "\n";
> extends 'DBIx::Class::Core';
> print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') .
> "\n";
>
> That prints:
> HAS BUILDARGS: YES
> HAS BUILDARGS: NO
>
> I was able to change this to YES-YES by adding Moo::Object to the front of
> my extends, which in the above example would look like:
>
> extends 'Moo::Object', 'DBIx::Class::Core';
>
> Is that the right thing to do when inheriting from a non-Moo class?

Adding Moo::Object manually like this is a supported way to override
the constructor
of whatever else you are inheriting from, and use a purely Moo style
constructor that
won't call the other parent.

That's only meant for cases where something is misbehaving, and will
break many things.
Doing it with DBIC will certainly break things s That should only be
needed if something is misbehaving.
It shouldn't be needed in your case, and I'm pretty certain it will
break things.  DBIC
does a fair amount of work in its constructors and you would be bypassing.

> Documentation on non-moo inheritance was minimal in the Moo docs, but maybe
> I missed it.  Note that I found this issue via a Moose result class which
> inherits from my Moo result base class which inherits from
> DBIx::Class::Core.  Something about that relationship structure requires
> BUILDARGS even though the involved code neither declares nor calls
> BUILDARGS.
BUILDARGS should not be required.  This is a bug in Moo.  I'm working
on a fix.  You
should be able to work around this by making sure your Moose classes are calling
__PACKAGE__->meta->make_immutable.  Another workaround would be
including *BUILDARGS = \&Moo::Object::BUILDARGS; in your Moo class.

>
> Another issue is this:
>
> package FooResult;
> use Moo;
> extends 'DBIx::Class::Core';
> has bar => ( is=>'ro' );
> FooResult->new( bar=>32 );
>
> Which then hangs with:
>
> Deep recursion on subroutine "DBIx::Class::Row::throw_exception" at
> /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1416.
> Deep recursion on subroutine "DBIx::Class::Row::result_source" at
> /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1568.
>
> I tried fiddling with FOREIGNBUILDARGS to see if I could produce arguments
> which made DBIC's new() happy but it was a fruitless effort.
Part of this I believe is a bug in DBIC, where a certain class of
errors can result in
deep recursion.  What the deep recursion issue is hiding is that
DBIC's ->new expects
a hashref of options, but you gave it a list.  The easiest option
would be to always pass
in options in hashref form ( FooResult->new({bar => 32}); ) but you
could also define a
FOREIGNBUILDARGS to do that transformation for you.

>
> At this point the error I am getting with the real application code is:
>
> DBIx::Class::Sims::load_sims(): Can't call method "new" on an undefined
> value at /home/aran/local-lib/lib/perl5/DBIx/Class/ResultSet.pm line 2590.
> at /home/aran/ziprecruiter/app/t/lib/Test/ZR/Schema.pm line 95
>
> Which is what lead me to the two previous examples.  As far as I can tell my
> Moo conversion is complete and there is something wrong with the argument
> processing between Moo and DBIC.

This looks like the result of bypassing DBIC's constructor by adding Moo::Object
to your extends.  The result_source isn't being initialized correctly,
because that is
done by DBIC's constructor.

>
> I'm using the latest DBIC (0.082800) and Moo (1.006).
>
> Any pointers, examples, words of wisdom, RTFMs, etc, appreciated.
>
> Thanks!
>
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive:
> http://www.grokbase.com/group/dbix-class@...

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: DBIC and Moo woes

Graham Knop
In reply to this post by Aran Deltac-2
On Thu, Oct 2, 2014 at 2:24 PM, Aran Deltac <[hidden email]> wrote:

> I've abstracted out my work to something more general.  I'm going to copy
> over and run the entire DBIC test suite against it and see what fails.
> There is some magic in the load_components bit as it uses some Moo internals
> to do the Moo extends and with properly.  Just posting here if anyone is
> curious.
>
> https://github.com/bluefeet/DBICx-Moo
>
> Aran
>
> On Wed, Oct 1, 2014 at 7:21 PM, Aran Deltac <[hidden email]> wrote:
>>
>> I've been converting a lot of @work's custom components, result, result
>> set, schema, and storage classes (yes, we even have custom storage classes)
>> to Moo roles and classes.
>>
>> I've just about completed it and have worked through a lot of issues, but
>> am left with one remaining issue which I'm stumped at and have been able to
>> whittle it down to a couple small examples:
>>
>> package FooResult;
>> use Moo;
>> print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') .
>> "\n";
>> extends 'DBIx::Class::Core';
>> print 'HAS BUILDARGS: ' . (FooResult->can('BUILDARGS') ? 'YES' : 'NO') .
>> "\n";
>>
>> That prints:
>> HAS BUILDARGS: YES
>> HAS BUILDARGS: NO
>>
>> I was able to change this to YES-YES by adding Moo::Object to the front of
>> my extends, which in the above example would look like:
>>
>> extends 'Moo::Object', 'DBIx::Class::Core';
>>
>> Is that the right thing to do when inheriting from a non-Moo class?
>> Documentation on non-moo inheritance was minimal in the Moo docs, but maybe
>> I missed it.  Note that I found this issue via a Moose result class which
>> inherits from my Moo result base class which inherits from
>> DBIx::Class::Core.  Something about that relationship structure requires
>> BUILDARGS even though the involved code neither declares nor calls
>> BUILDARGS.
>>
>> Another issue is this:
>>
>> package FooResult;
>> use Moo;
>> extends 'DBIx::Class::Core';
>> has bar => ( is=>'ro' );
>> FooResult->new( bar=>32 );
>>
>> Which then hangs with:
>>
>> Deep recursion on subroutine "DBIx::Class::Row::throw_exception" at
>> /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1416.
>> Deep recursion on subroutine "DBIx::Class::Row::result_source" at
>> /home/aran/local-lib/lib/perl5/DBIx/Class/Row.pm line 1568.
>>
>> I tried fiddling with FOREIGNBUILDARGS to see if I could produce arguments
>> which made DBIC's new() happy but it was a fruitless effort.
>>
>> At this point the error I am getting with the real application code is:
>>
>> DBIx::Class::Sims::load_sims(): Can't call method "new" on an undefined
>> value at /home/aran/local-lib/lib/perl5/DBIx/Class/ResultSet.pm line 2590.
>> at /home/aran/ziprecruiter/app/t/lib/Test/ZR/Schema.pm line 95
>>
>> Which is what lead me to the two previous examples.  As far as I can tell
>> my Moo conversion is complete and there is something wrong with the argument
>> processing between Moo and DBIC.
>>
>> I'm using the latest DBIC (0.082800) and Moo (1.006).
>>
>> Any pointers, examples, words of wisdom, RTFMs, etc, appreciated.
>>
>> Thanks!
>
>
>
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive:
> http://www.grokbase.com/group/dbix-class@...

Generally, using DBIC with Moo should be as simple as `use Moo;
extends "DBIx::Class...";`
There appears to be a few bugs there to fix, but I'd prefer to
approach things from
that angle, making a special Moo+DBIC module unnecessary.

There's a few things I don't like about your implementation.  Reaching
into Moo's internals
like that is particularly gross.  If you want to change superclasses
or compose roles, the
correct interface to use is calling the class's "extends" or "with"
subs.  Also, trying to detect
role vs class is generally a bad idea.  It should be handled as a
separate interface.  Trying to
detect that also resulted in loading Moose, with the speed hit and XS
requirement that implies.

Personally, I don't see much value in trying to adapt Moo to use the
__PACKAGE__->method
style syntax for anything.  If I wanted to mesh the two styles, I'd go
for sugar like
DBIx::Class::Candy provides.  The automatic prefixing seems to be the
only thing provided by
load_components, and that is just as easily done in a helper sub.

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: DBIC and Moo woes

Aran Deltac-2
In reply to this post by Aran Deltac-2
Thanks guys - I'll take a look now.

making a special Moo+DBIC module unnecessary.

Right!  I wasn't expecting this to be going on CPAN, just a proof of concept - trying to bang Moo into DBIC's test suite while changing the test suite as little as possible.

Aran

On Wed, Oct 22, 2014 at 10:15 AM, Peter Rabbitson <[hidden email]> wrote:
On 10/02/2014 04:21 AM, Aran Deltac wrote:
I've been converting a lot of @work's custom components, result, result
set, schema, and storage classes (yes, we even have custom storage
classes) to Moo roles and classes.

Hi bluefeet,

I think your original issues should be all solved by the latest Moo released on cpan a bit ago (1.006001). Can you please test and report back. If this is indeed the case I will bump the DBIC dependency to get the combo into the wild.


_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: DBIC and Moo woes

Aran Deltac-2
I'm now running into a lot of these errors:

DBIx::Class::Storage::DBI::SQLite::_dbi_attrs_for_bind(): POSSIBLE *PAST* DATA CORRUPTION detected - see DBIx::Class::Storage::DBI::SQLite/RT79576 or http://v.gd/DBIC_SQLite_RT79576 for further details or set $ENV{DBIC_RT79576_NOWARN} to disable this warning.

And it also looks like column inflation is not working right (my datetime object are no longer being inflated).

Hopefully this is all my fault, something funky about how I put Moo in.

Digging in, but may not get back to ya'all today.

Aran

On Thu, Oct 23, 2014 at 6:44 AM, Aran Deltac <[hidden email]> wrote:
Thanks guys - I'll take a look now.

making a special Moo+DBIC module unnecessary.

Right!  I wasn't expecting this to be going on CPAN, just a proof of concept - trying to bang Moo into DBIC's test suite while changing the test suite as little as possible.

Aran

On Wed, Oct 22, 2014 at 10:15 AM, Peter Rabbitson <[hidden email]> wrote:
On 10/02/2014 04:21 AM, Aran Deltac wrote:
I've been converting a lot of @work's custom components, result, result
set, schema, and storage classes (yes, we even have custom storage
classes) to Moo roles and classes.

Hi bluefeet,

I think your original issues should be all solved by the latest Moo released on cpan a bit ago (1.006001). Can you please test and report back. If this is indeed the case I will bump the DBIC dependency to get the combo into the wild.



_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: DBIC and Moo woes

Aran Deltac-2
In reply to this post by Aran Deltac-2
Thanks for all the work on this guys.  Things seem to be working well with one small issue and one big-ish one.  The small one is that mixing load_components() and Moo's extends() doesn't work.  Easy enough to fix and makes sense.

The larger issue is that now, with latest Moo, the method resolution order changes from 'c3' to 'dfs' which breaks a bunch of things for me.  For example DBIx::Class::InflateColumn::DateTime, under c3, comes before DBIx::Class::Row, but with dfs it comes after and column inflation stops functioning.

Doing this in my result classes seems to fix it:

use Moo;
use mro 'c3';

I should be complete with my DBIC->Moo work within the next day or two and I'm hoping based on early success that all will be well.

Aran

On Sat, Dec 20, 2014 at 6:29 AM Peter Rabbitson <[hidden email]> wrote:
On 10/02/2014 04:21 AM, Aran Deltac wrote:
> I've been converting a lot of @work's custom components, result, result
> set, schema, and storage classes (yes, we even have custom storage
> classes) to Moo roles and classes.
>

Hi Aran,

Just wanted to followup whether the current stable DBIC and Moo versions
resolve your issues.

Thanks!


_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Loading...