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");