Open rmloveland opened 4 years ago
had this basic retry loop in my back pocket, figure I'll post it here in case it's useful
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/ say /;
use DBI;
use Data::Dumper;
use Try::Tiny;
my $db_config = { AutoCommit => -1, pg_errorlevel => 2 };
my $dbh = DBI->connect( "dbi:Pg:dbname=bank;host=localhost;port=26257",
'root', '', $db_config );
# We will manage the transaction lifecycle in our code.
$dbh->{AutoCommit} = undef;
$dbh->{RaiseError} = 1;
END {
$dbh->disconnect;
}
sub create_accounts {
my $dbh = shift;
my @stmts = (
q[CREATE TABLE IF NOT EXISTS accounts (id INT PRIMARY KEY, balance INT)],
q[UPSERT INTO accounts (id, balance) VALUES (1, 1000), (2, 250)],
);
$dbh->do($_) for @stmts;
$dbh->commit;
}
sub print_balances {
my $dbh = shift;
my @rows = $dbh->selectrow_array(q[SELECT id, balance FROM accounts]);
$dbh->commit;
say qq[Balances at], localtime(time);
say for @rows;
}
sub delete_accounts {
my $dbh = shift;
$dbh->do(q[DELETE FROM bank.accounts]);
$dbh->commit;
}
sub run_transaction {
my ( $dbh, $sub ) = @_;
my $retries = 0;
my $max_retries = 3;
RETRY: while (1) {
$retries++;
if ( $retries == $max_retries ) {
die qq[Transaction did not succeed after $retries retries\n];
}
try {
$sub->($dbh);
}
catch {
say qq[Had an error of type: ], Dumper $dbh->state;
# Capture the PG error code
my $SQL_STATE = $dbh->state;
if ( $SQL_STATE eq q[40001] ) {
eval { $dbh->rollback };
my $sleep_secs = int( 2**$retries );
say qq[Sleeping for $sleep_secs seconds ...];
sleep($sleep_secs);
next RETRY;
}
else {
# This is not a transaction retry error, so your
# application will need to deal with it separately.
}
}
}
}
sub test_retry_loop {
my $dbh = shift;
my @stmts =
( q[SELECT now()], q[SELECT crdb_internal.force_retry('1s'::INTERVAL)], );
for (@stmts) {
say qq[About to run SQL: '$_'];
$dbh->do($_);
}
}
sub transfer_funds { }
sub main {
my $dbh = shift;
my $stmt = qq[SELECT now()];
my @answer = $dbh->selectrow_array($stmt);
say Dumper @answer;
# Test retry loop
say qq[Testing retry loop ...];
run_transaction( $dbh, \&test_retry_loop );
}
main($dbh);
Richard Loveland (rmloveland) commented:
We have had a user request for a Perl driver.
AFAICT from some light usage, DBI (with the [DBD::Pg](https://metacpan.org/pod/DBD::Pg] backend] works fine. At least I haven't encountered any problems yet. E.g., prepared statements with placeholders work.
Estimated scope of work:
Jira Issue: DOC-450