Cleanup ResultSourceHandle handling after M.A.D. introduction
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSourceHandle.pm
CommitLineData
aec3eff1 1package DBIx::Class::ResultSourceHandle;
2
3use strict;
4use warnings;
aec3eff1 5
6use base qw/DBIx::Class/;
7
4376a157 8use Storable qw/nfreeze thaw/;
9use DBIx::Class::Exception;
10use Try::Tiny;
11
12use namespace::clean;
13
aec3eff1 14use overload
5f946071 15 # on some RH perls the following line causes serious performance problem
16 # see https://bugzilla.redhat.com/show_bug.cgi?id=196836
3441fd57 17 q/""/ => sub { __PACKAGE__ . ":" . shift->source_moniker; },
aec3eff1 18 fallback => 1;
19
4376a157 20__PACKAGE__->mk_group_accessors('simple' => qw/schema source_moniker _detached_source/);
aec3eff1 21
4146e3da 22# Schema to use when thawing.
23our $thaw_schema;
24
aec3eff1 25=head1 NAME
26
4376a157 27DBIx::Class::ResultSourceHandle - Serializable pointers to ResultSource instances
aec3eff1 28
29=head1 DESCRIPTION
30
4376a157 31Currently instances of this class are used to allow proper serialization of
32L<ResultSources|DBIx::Class::ResultSource> (which may contain unserializable
33elements like C<CODE> references).
aec3eff1 34
4376a157 35Originally this module was used to remove the fixed link between
36L<Rows|DBIx::Class::Row>/L<ResultSets|DBIx::Class::ResultSet> and the actual
37L<result source objects|DBIx::Class::ResultSource> in order to obviate the need
38of keeping a L<schema instance|DBIx::Class::Schema> constantly in scope, while
39at the same time avoiding leaks due to circular dependencies. This is however
40no longer needed after introduction of a proper mutual-assured-destruction
41contract between a C<Schema> instance and its C<ResultSource> registrants.
aec3eff1 42
43=head1 METHODS
44
45=head2 new
46
47=cut
48
49sub new {
4376a157 50 my ($class, $args) = @_;
51 my $self = bless $args, ref $class || $class;
aec3eff1 52
4376a157 53 unless( ($self->{schema} || $self->{_detached_source}) && $self->{source_moniker} ) {
54 my $err = 'Expecting a schema instance and a source moniker';
55 $self->{schema}
56 ? $self->{schema}->throw_exception($err)
57 : DBIx::Class::Exception->throw($err)
58 }
aec3eff1 59
4376a157 60 $self;
aec3eff1 61}
62
63=head2 resolve
64
3441fd57 65Resolve the moniker into the actual ResultSource object
aec3eff1 66
67=cut
68
4376a157 69sub resolve {
70 return $_[0]->{schema}->source($_[0]->source_moniker) if $_[0]->{schema};
71
72 $_[0]->_detached_source || DBIx::Class::Exception->throw( sprintf (
73 # vague error message as this is never supposed to happen
74 "Unable to resolve moniker '%s' - please contact the dev team at %s",
75 $_[0]->source_moniker,
76 'http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class.pm#GETTING_HELP/SUPPORT',
77 ), 'full_stacktrace');
78}
aec3eff1 79
7137528d 80=head2 STORABLE_freeze
81
82Freezes a handle.
83
84=cut
85
aec3eff1 86sub STORABLE_freeze {
4376a157 87 my ($self, $cloning) = @_;
4146e3da 88
4376a157 89 my $to_serialize = { %$self };
d4daee7b 90
4376a157 91 delete $to_serialize->{schema};
92 delete $to_serialize->{_detached_source};
93 $to_serialize->{_frozen_from_class} = $self->{schema}
94 ? $self->{schema}->class($self->source_moniker)
95 : $self->{_detached_source}->result_class
96 ;
7cfda9a6 97
4376a157 98 nfreeze($to_serialize);
aec3eff1 99}
100
7137528d 101=head2 STORABLE_thaw
102
4146e3da 103Thaws frozen handle. Resets the internal schema reference to the package
48580715 104variable C<$thaw_schema>. The recommended way of setting this is to use
323e0bd0 105C<< $schema->thaw($ice) >> which handles this for you.
7137528d 106
107=cut
108
aec3eff1 109sub STORABLE_thaw {
4376a157 110 my ($self, $cloning, $ice) = @_;
111 %$self = %{ thaw($ice) };
112
113 my $from_class = delete $self->{_frozen_from_class};
114
115 if( $thaw_schema ) {
116 $self->schema( $thaw_schema );
117 }
118 elsif( my $rs = $from_class->result_source_instance ) {
119 # in the off-chance we are using CDBI-compat and have leaked $schema already
120 if( my $s = try { $rs->schema } ) {
121 $self->schema( $s );
3a81f59b 122 }
123 else {
4376a157 124 $rs->source_name( $self->source_moniker );
125 $rs->{_detached_thaw} = 1;
126 $self->_detached_source( $rs );
3a81f59b 127 }
4376a157 128 }
129 else {
130 DBIx::Class::Exception->throw(
131 "Thaw failed - original result class '$from_class' does not exist on this system"
132 );
133 }
aec3eff1 134}
135
4146e3da 136=head1 AUTHOR
137
138Ash Berlin C<< <ash@cpan.org> >>
139
140=cut
141
aec3eff1 1421;