DBIx-Class-Async

 view release on metacpan or  search on metacpan

lib/DBIx/Class/Async.pm  view on Meta::CPAN

        delete $db->{_health_check_timer};
    }

    # 2. Remove and stop each worker.
    #
    # CRITICAL ORDER: remove() MUST be called BEFORE stop().
    #
    # IO::Async::Function::stop() sets an internal {stopping} flag and
    # begins tearing down IPC channels. Once that flag is set, remove()
    # silently fails - the notifier stays in the loop's internal registry,
    # keeping the loop (and its SIGCHLD handler) alive past the point where
    # we expect them to be freed. During Perl global destruction the loop's
    # XS destructor then accesses already-freed memory -> SEGV.
    #
    # Calling remove() first detaches the Function and all its child
    # notifiers (Streams, Handles, Processes) cleanly, then stop() signals
    # the worker processes to exit and returns a Future we can await.
    if ($db->{_workers}) {
        my @stop_futures;
        foreach my $worker_info (@{ $db->{_workers} }) {
            my $instance = $worker_info->{instance} or next;

lib/DBIx/Class/Async.pm  view on Meta::CPAN

                    }
                    elsif ($operation eq 'txn_commit') {
                        $schema->storage->txn_commit;
                        return { success => 1 };
                    }
                    elsif ($operation eq 'txn_rollback') {
                        $schema->storage->txn_rollback;
                        return { success => 1 };
                    }
                    elsif ($operation eq 'ping') {
                        my $alive = eval { $schema->storage->dbh->do("SELECT 1") };
                        return { success => ($alive ? 1 : 0), status => "pong" };
                    }
                    else {
                        die "Unknown operation: $operation";
                    }
                }
                catch {
                    warn "[PID $$] Worker execution error: $_"
                        if ASYNC_TRACE;
                    return { error => "$_", success => 0 };
                };

lib/DBIx/Class/Async/Schema.pm  view on Meta::CPAN

    # 1. Retrieve the cached entry
    my $cached = $self->{_sources_cache}{$source_name};

    # 2. Check if we need to (re)fetch:
    #    Either we have no entry, or it's a raw HASH (autovivification artifact)
    if (!$cached || !blessed($cached)) {

        # Clean up any "ghost" hash before re-fetching
        delete $self->{_sources_cache}{$source_name};

        # 3. Use the persistent provider to keep ResultSource objects alive
        $self->{_metadata_provider} ||= do {
            my $class = $self->{_async_db}->{_schema_class};
            eval "require $class" or die "Could not load schema class $class: $@";
            $class->connect(@{$self->{_async_db}->{_connect_info}});
        };

        # 4. Fetch the source and validate its blessing
        my $source_obj = eval { $self->{_metadata_provider}->source($source_name) };

        if (blessed($source_obj)) {

t/012-health-checks.t  view on Meta::CPAN

$schema->await($schema->deploy({ add_drop_table => 1 }));

subtest 'Worker Health Check' => sub {
    my $healthy_workers = eval { $schema->health_check->get };

    if ($@) {
        fail("health_check died with error: $@");
    }
    else {
        is($healthy_workers, $expected_workers, "All $expected_workers configured workers are healthy");
        cmp_ok($healthy_workers, '>', 0, 'At least one worker is alive');
    }
};

subtest 'Health Stability' => sub {
    $schema->resultset('User')->create({ name => 'HealthCheckUser', email => 'hc@test.com' })->get;

    my $after_query_health = $schema->health_check->get;
    is($after_query_health, $expected_workers, 'Workers remain healthy after database operations');
};

t/103-clone.t  view on Meta::CPAN

    # 4. Access the row data
    if (@results) {
        is($results[0]->name, 'Original', 'Data retrieved via clone is correct');
    }

    #done_testing;
};

subtest 'Storage Alignment' => sub {

    my $clone = $schema->clone(); # Keep the clone alive in this scope
    is($clone->storage->schema, $clone, 'Clone storage points to cloned schema');
    isnt($clone->storage, $schema->storage, 'Clone has its own storage instance');
};

$schema->disconnect;

done_testing;

t/110-disconnect.t  view on Meta::CPAN

      async_loop   => $loop,
      cache_ttl    => 60,
    },
);

$schema->await($schema->deploy({ add_drop_table => 1 }));

subtest "Verify Active Connection" => sub {
    ok($schema->{_async_db}, "Internal async_db manager is initialized");

    # Perform a quick operation to ensure workers are alive
    my $rs = $schema->resultset('User');
    isa_ok($rs, 'DBIx::Class::Async::ResultSet');

    # Ensure metadata cache is populated
    my $class = $schema->class('User');
    ok($class, "Metadata cache is populated (Class: $class)");
    ok(keys %{$schema->{_sources_cache}}, "Sources cache is not empty");
};

subtest "Execution of disconnect()" => sub {



( run in 2.634 seconds using v1.01-cache-2.11-cpan-df04353d9ac )