Skip to content

Instantly share code, notes, and snippets.

@Irfy
Created April 22, 2019 11:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Irfy/5543b32efdb88777b61aa249f94894cc to your computer and use it in GitHub Desktop.
Save Irfy/5543b32efdb88777b61aa249f94894cc to your computer and use it in GitHub Desktop.
Based on the pseudocode sample above, a `next/last/redo` could be executed on the second try,
without being executed in the first try, for *at least* the following reasons:
1. Initial transaction setup caused a retry with an unconditional `next/last/redo` in the body of the coderef
2. Some action in the coderef, before an unconditional `next/last/redo` caused a retry.
3. An unexpected or undesirable situation after a *skipped, conditional* `next/last/redo` causes a retry
(like optimistic locking failure). On the second try, conditions have changed (e.g. modification of data
in the database) and this changes the path taken by the code, triggering the *conditional* `next/last/redo`,
that wasn't triggered on the first try, due to different conditions in that run.
use strict;
use tx_exec qw(tx_exec);
for $customer_id (<>) { # manually supplied list of customer IDs
my ($tx_ret, $sub_ret) = tx_exec ("migrate_customer", sub {
# before we reach here, we will have created some transaction context, and already accessed the database
# so a retry can be triggered even before we enter our coderef
my ($tx) = @_;
my $customer = $tx->load_customer ($customer_id); # we could trigger a retry due to a timeout here
if (inconsistent_state($customer)) {
$logger->warn ("Inconsistent customer state, skipping");
next; # inconspicuous `next`, attempting to skip to the next iteration of our local for-loop
}
# migrate the customer object to a different place/system, mark it as migrated in our database
});
# upon exiting our sub, our tx_exec could detect a concurrent modification of data also modified by us, that started after
# our transaction and finished before it, necessitating a retry (classic optimistic locking). in the retry, we could
# end up in the inconsistent_state clause by chance, or a mistake elswhere in the system, even a temporary or incomplete
# manual modification in the database, that would make the customer object inconsistent according to some metrics.
}
use strict;
use warnings;
sub tx_exec {
# execute client code in the context of an application-level transaction
# things that can temporarily go wrong and cause a retry:
# * connectivity issues
# * lock timeout
# * concurrent modification (faster than us in optimistic locking)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment