DBIx-Class-Async
view release on metacpan or search on metacpan
lib/DBIx/Class/Async/Schema.pm view on Meta::CPAN
$METRICS->set($name, @args);
}
return;
}
sub _resolve_source {
my ($self, $source_name) = @_;
croak "Missing source name." unless defined $source_name;
my $schema_class = $self->{_async_db}{_schema_class};
croak "Schema class not found." unless defined $schema_class;
# 1. Ask the main DBIC Schema class for the source metadata
# We call this on the class name, not an instance, to stay "light"
my $source = eval { $schema_class->source($source_name) };
if ($@ || !$source) {
croak "Could not resolve source '$source_name' in $schema_class: $@";
}
# 2. Extract only what we need for the Async side
return {
result_class => $source->result_class,
columns => [ $source->columns ],
relationships => {
# We map relationships to know how to handle joins/prefetch later
map { $_ => $source->relationship_info($_) } $source->relationships
},
};
}
sub _build_inflator_map {
my ($self, $schema) = @_;
my $map = {};
foreach my $source_name ($schema->sources) {
my $source = $schema->source($source_name);
foreach my $col ($source->columns) {
my $info = $source->column_info($col);
# Extract both inflate and deflate coderefs
if ($info->{deflate} || $info->{inflate}) {
$map->{$source_name}{$col} = {
deflate => $info->{deflate},
inflate => $info->{inflate},
};
}
# Explicit check for JSON Serializer
elsif ($info->{serializer_class}
&& $info->{serializer_class} eq 'JSON') {
require JSON;
my $json = JSON->new->utf8->allow_nonref;
$map->{$source_name}{$col} = {
inflate => sub {
my $val = shift;
return $val if !defined $val || ref($val);
my $decoded;
eval {
$decoded = $json->decode($val); 1;
}
or do {
warn "Failed to inflate JSON in $col: $@ (Value: $val)";
return $val;
};
return $decoded;
},
deflate => sub {
my $val = shift;
return $val if !defined $val || !ref($val);
return $json->encode($val);
},
};
}
}
}
return $map;
}
=head1 METADATA & REFLECTION
=over 4
=item B<source( $source_name )>
Returns the L<DBIx::Class::ResultSource> for the given name.
Unlike standard DBIC, this uses a B<persistent metadata provider> (a cached
internal schema) to ensure that ResultSource objects remain stable across
async calls without re-connecting to the database unnecessarily.
=item B<sources()>
Returns a list of all source names available in the schema. This creates a
temporary, light-weight connection to extract the current schema structure
and then immediately disconnects to save resources.
=item B<class( $source_name )>
Returns the Result Class string (e.g., C<MyApp::Schema::Result::User>) for
the given source. Useful for dynamic inspections.
=item B<schema_class()>
Returns the name of the base L<DBIx::Class> schema class being proxied.
=item B<schema_version()>
Returns the version number defined in your DBIC Schema class, if available.
=back
=head1 TRANSACTION MANAGEMENT
=over 4
=item B<txn_begin / txn_commit / txn_rollback>
These methods return L<Future> objects. Because workers are persistent,
calling C<txn_begin> pins your current logic to a specific worker until
C<commit> or C<rollback> is called.
B<Note:> Use these carefully in an async loop to avoid "Worker Starvation"
where all workers are waiting on long-running manual transactions.
( run in 1.810 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )