DBIO-PostgreSQL-EV

 view release on metacpan or  search on metacpan

t/17-concurrency-live.t  view on Meta::CPAN

# starvation ("one conn preferred, the rest starve") is exactly the karr #13
# bug the shift-fix cured; verified empirically by running this file against
# the still-installed pop core (RED) vs. the fixed shift core (GREEN).
#
# ($rot_pids[i] == $rot_pids[i-4] alone is NOT a discriminator: if all pids
#  are identical it holds trivially. It is the POSITIVE FIFO signature only
#  once (B1) has established that there really are 4 distinct pids.)

my @rot_pids;
my $slots = $storage->pool->max_size;      # 4
for my $iter (1 .. 2 * $slots) {           # 2 full rounds = 8 iterations
  # WHERE id=1 pins the result to exactly one row; the sole selected item is
  # the backend pid (index 0). Awaiting here (not batching) is the whole
  # point — it forces the pool fully idle before the next acquire, so acquire
  # ORDER, not fan-out, is what is under test.
  my $f = $storage->select_async($table, [ \'pg_backend_pid()' ], { id => 1 });
  await_guarded($f, "FIFO rotation iter $iter");
  my @rows = $f->get;
  is scalar(@rows), 1, "rotation iter $iter: exactly one row";
  push @rot_pids, $rows[0][0];
  is $storage->pool->size, 4, "rotation iter $iter: pool still 4 (churn, no growth)";
}

# (B1) FIFO rotates through EVERY pooled backend — the primary LIFO
# discriminator. Under pop this set collapses to size 1.
my %rot_seen;
$rot_seen{$_}++ for @rot_pids;
is scalar(keys %rot_seen), $slots,
  "sequential churn visited all $slots distinct backends (FIFO rotation; LIFO would stick to 1)";

# (B2) No two CONSECUTIVE iterations reused the same backend: shift always
# hands out a different conn than the one release just pushed to the back.
# Under LIFO every consecutive pair is identical.
my $consecutive_repeats = 0;
for my $i (1 .. $#rot_pids) {
  $consecutive_repeats++ if $rot_pids[$i] == $rot_pids[$i - 1];
}
is $consecutive_repeats, 0,
  'no consecutive iteration reused the same backend (FIFO hands out a fresh conn; LIFO repeats every time)';

# (B3) Positive FIFO signature: iteration i reuses the SAME backend as

t/19-copy-in-regression.t  view on Meta::CPAN

# and the Storage's CRUD Future fails.
#
# The fix (Storage.pm:copy_in) waits for EV::Pg's SECOND callback firing
# (the one that delivers the final cmd_tuples after libpq has actually
# finished the COPY) before releasing the connection. This test would
# fail loudly against the original implementation and pass against the
# fixed one. It runs the cycle THREE times back-to-back because the bug
# is timing-sensitive: the pool typically has 5 idle slots, so the first
# copy_in is usually followed by an acquire that picks a DIFFERENT idle
# connection; the bug surfaces once the same Storage cycles the same
# physical connection. Three iterations exercise both code paths.
#
# Pre-fix behavior on this test:
#   - iteration 1: first select_async after copy_in picks a different
#     idle connection (or, if pool_size == 1, hits the still-busy one);
#     not always a hard fail, so we run it three times.
#   - iterations 2+3: same connection gets reused, libpq returns
#     "another command is already in progress", select_async Future fails.
#
# Post-fix behavior:
#   - every iteration's follow-up select_async succeeds and returns the
#     rows that were just COPY-loaded.

BEGIN {
  plan skip_all => 'Set DBIO_TEST_PG_DSN to run integration tests'
    unless $ENV{DBIO_TEST_PG_DSN};
}



( run in 1.754 second using v1.01-cache-2.11-cpan-f03e8824b8d )