DBIx-QuickORM

 view release on metacpan or  search on metacpan

lib/DBIx/QuickORM/Connection/Transaction.pm  view on Meta::CPAN


=cut

sub init {
    my $self = shift;

    croak "A transaction ID is required" unless $self->{+ID};

    # Hold the connection weakly. The connection holds its transactions weakly in
    # turn, so this back-reference does not create a strong cycle; weakening it
    # keeps a transaction from pinning its connection alive and from dragging the
    # whole connection into a dump or deep comparison of the txn.
    weaken($self->{+CONNECTION}) if $self->{+CONNECTION};

    $self->{+RESULT} = undef;

    $self->{+ON_SUCCESS}    = [$self->{+ON_SUCCESS}]    if 'CODE' eq ref($self->{+ON_SUCCESS});
    $self->{+ON_FAIL}       = [$self->{+ON_FAIL}]       if 'CODE' eq ref($self->{+ON_FAIL});
    $self->{+ON_COMPLETION} = [$self->{+ON_COMPLETION}] if 'CODE' eq ref($self->{+ON_COMPLETION});
}

lib/DBIx/QuickORM/Connection/Transaction.pm  view on Meta::CPAN


    # last QORM_TRANSACTION unwinds to the innermost dynamically-enclosing
    # transaction callback, which is not necessarily this transaction's. When a
    # nested (callback-managed) transaction is open, committing or rolling back
    # an outer transaction object would resolve the wrong (inner) one, so refuse.
    #
    # The connection is held weakly (the connection already holds its
    # transactions weakly, so this just avoids following the back-ref in a dump
    # or deep comparison). By the time commit()/rollback() reach this point we
    # are running inside the transaction's own action, so the connection is
    # alive and it always has a current transaction (at least this one) --
    # neither being missing is a normal case, so croak rather than skip the
    # check silently.
    my $con = $self->{+CONNECTION}
        or croak "Cannot $op a transaction whose connection is gone";
    my $current = $con->current_txn
        or croak "Cannot $op: the connection reports no current transaction";
    return if $current == $self;

    croak "Cannot $op an outer transaction from within a nested transaction; resolve the innermost transaction first";
}

lib/DBIx/QuickORM/Manual/Caching.pm  view on Meta::CPAN

The cache lives on the connection (L<DBIx::QuickORM::Connection>), held by its
row manager (L<DBIx::QuickORM::RowManager>). Two separate connections each have
their own cache, so the same database row loaded through two connections yields
two distinct objects. This is intentional: each connection has its own
transaction state and its own view of the data. See
L<DBIx::QuickORM::Manual::Connections> for the connection lifecycle.

=head1 WEAK REFERENCES: NO LEAKS

Cached rows are held by B<weak> reference. The cache lets you reuse a row while
it is still alive somewhere in your program, but it does not keep rows alive on
its own. Once nothing else references a row, it is garbage collected and its
cache entry disappears. Loading many rows and then dropping them does not grow
the cache without bound.

A consequence: identity is only guaranteed for as long as you hold a reference.
If you drop every reference to a row and fetch it again, you may get a fresh
object - but it will still be the only one, so the one-copy guarantee holds.

=head1 INTERACTION WITH SELECT / INSERT / UPDATE / DELETE

t/AI/cache_fixes.t  view on Meta::CPAN

};

subtest dead_weak_entries_are_purged => sub {
    my $source = $con->source('solo');
    my $sh     = $con->handle('solo');

    my @rows = map { $sh->insert({name => "purge_$_"}) } 1 .. 5;
    my @pks  = map { $_->field('solo_id') } @rows;

    my $bucket = $manager->{cache}{$source->source_orm_name};
    ok((grep { defined $bucket->{$_} } keys %$bucket) >= 5, "all five rows are cached and alive");

    @rows = ();    # Drop the only strong references; weak cache entries go undef.

    my $dead = grep { !defined $bucket->{$_} } keys %$bucket;
    ok($dead >= 5, "dead entries linger in the bucket before a purge");

    # A lookup that hits a dead entry triggers the purge.
    my $miss = $manager->do_cache_lookup($source, undef, [$pks[0]], undef);
    ok(!$miss, "lookup of a garbage-collected row misses");

worktrees/audit-fixes-master/lib/DBIx/QuickORM/Connection/Transaction.pm  view on Meta::CPAN


=cut

sub init {
    my $self = shift;

    croak "A transaction ID is required" unless $self->{+ID};

    # Hold the connection weakly. The connection holds its transactions weakly in
    # turn, so this back-reference does not create a strong cycle; weakening it
    # keeps a transaction from pinning its connection alive and from dragging the
    # whole connection into a dump or deep comparison of the txn.
    weaken($self->{+CONNECTION}) if $self->{+CONNECTION};

    $self->{+RESULT} = undef;

    $self->{+ON_SUCCESS}    = [$self->{+ON_SUCCESS}]    if 'CODE' eq ref($self->{+ON_SUCCESS});
    $self->{+ON_FAIL}       = [$self->{+ON_FAIL}]       if 'CODE' eq ref($self->{+ON_FAIL});
    $self->{+ON_COMPLETION} = [$self->{+ON_COMPLETION}] if 'CODE' eq ref($self->{+ON_COMPLETION});
}

worktrees/audit-fixes-master/lib/DBIx/QuickORM/Connection/Transaction.pm  view on Meta::CPAN


    # last QORM_TRANSACTION unwinds to the innermost dynamically-enclosing
    # transaction callback, which is not necessarily this transaction's. When a
    # nested (callback-managed) transaction is open, committing or rolling back
    # an outer transaction object would resolve the wrong (inner) one, so refuse.
    #
    # The connection is held weakly (the connection already holds its
    # transactions weakly, so this just avoids following the back-ref in a dump
    # or deep comparison). By the time commit()/rollback() reach this point we
    # are running inside the transaction's own action, so the connection is
    # alive and it always has a current transaction (at least this one) --
    # neither being missing is a normal case, so croak rather than skip the
    # check silently.
    my $con = $self->{+CONNECTION}
        or croak "Cannot $op a transaction whose connection is gone";
    my $current = $con->current_txn
        or croak "Cannot $op: the connection reports no current transaction";
    return if $current == $self;

    croak "Cannot $op an outer transaction from within a nested transaction; resolve the innermost transaction first";
}

worktrees/audit-fixes-master/lib/DBIx/QuickORM/Manual/Caching.pm  view on Meta::CPAN

The cache lives on the connection (L<DBIx::QuickORM::Connection>), held by its
row manager (L<DBIx::QuickORM::RowManager>). Two separate connections each have
their own cache, so the same database row loaded through two connections yields
two distinct objects. This is intentional: each connection has its own
transaction state and its own view of the data. See
L<DBIx::QuickORM::Manual::Connections> for the connection lifecycle.

=head1 WEAK REFERENCES: NO LEAKS

Cached rows are held by B<weak> reference. The cache lets you reuse a row while
it is still alive somewhere in your program, but it does not keep rows alive on
its own. Once nothing else references a row, it is garbage collected and its
cache entry disappears. Loading many rows and then dropping them does not grow
the cache without bound.

A consequence: identity is only guaranteed for as long as you hold a reference.
If you drop every reference to a row and fetch it again, you may get a fresh
object - but it will still be the only one, so the one-copy guarantee holds.

=head1 INTERACTION WITH SELECT / INSERT / UPDATE / DELETE

worktrees/audit-fixes-master/t/AI/cache_fixes.t  view on Meta::CPAN

};

subtest dead_weak_entries_are_purged => sub {
    my $source = $con->source('solo');
    my $sh     = $con->handle('solo');

    my @rows = map { $sh->insert({name => "purge_$_"}) } 1 .. 5;
    my @pks  = map { $_->field('solo_id') } @rows;

    my $bucket = $manager->{cache}{$source->source_orm_name};
    ok((grep { defined $bucket->{$_} } keys %$bucket) >= 5, "all five rows are cached and alive");

    @rows = ();    # Drop the only strong references; weak cache entries go undef.

    my $dead = grep { !defined $bucket->{$_} } keys %$bucket;
    ok($dead >= 5, "dead entries linger in the bucket before a purge");

    # A lookup that hits a dead entry triggers the purge.
    my $miss = $manager->do_cache_lookup($source, undef, [$pks[0]], undef);
    ok(!$miss, "lookup of a garbage-collected row misses");

worktrees/dbic-compat-native-features/lib/DBIx/QuickORM/Manual/Caching.pm  view on Meta::CPAN

The cache lives on the connection (L<DBIx::QuickORM::Connection>), held by its
row manager (L<DBIx::QuickORM::RowManager>). Two separate connections each have
their own cache, so the same database row loaded through two connections yields
two distinct objects. This is intentional: each connection has its own
transaction state and its own view of the data. See
L<DBIx::QuickORM::Manual::Connections> for the connection lifecycle.

=head1 WEAK REFERENCES: NO LEAKS

Cached rows are held by B<weak> reference. The cache lets you reuse a row while
it is still alive somewhere in your program, but it does not keep rows alive on
its own. Once nothing else references a row, it is garbage collected and its
cache entry disappears. Loading many rows and then dropping them does not grow
the cache without bound.

A consequence: identity is only guaranteed for as long as you hold a reference.
If you drop every reference to a row and fetch it again, you may get a fresh
object - but it will still be the only one, so the one-copy guarantee holds.

=head1 INTERACTION WITH SELECT / INSERT / UPDATE / DELETE

worktrees/dbic-compat-native-features/t/AI/cache_fixes.t  view on Meta::CPAN

};

subtest dead_weak_entries_are_purged => sub {
    my $source = $con->source('solo');
    my $sh     = $con->handle('solo');

    my @rows = map { $sh->insert({name => "purge_$_"}) } 1 .. 5;
    my @pks  = map { $_->field('solo_id') } @rows;

    my $bucket = $manager->{cache}{$source->source_orm_name};
    ok((grep { defined $bucket->{$_} } keys %$bucket) >= 5, "all five rows are cached and alive");

    @rows = ();    # Drop the only strong references; weak cache entries go undef.

    my $dead = grep { !defined $bucket->{$_} } keys %$bucket;
    ok($dead >= 5, "dead entries linger in the bucket before a purge");

    # A lookup that hits a dead entry triggers the purge.
    my $miss = $manager->do_cache_lookup($source, undef, [$pks[0]], undef);
    ok(!$miss, "lookup of a garbage-collected row misses");



( run in 2.281 seconds using v1.01-cache-2.11-cpan-14f38c9f855 )