# # (c) Jan Gehring # # vim: set ts=2 sw=2 tw=0: # vim: set expandtab: =head1 NAME Rex::Transaction - Transaction support. =head1 DESCRIPTION With this module you can define transactions and rollback szenarios on failure. =head1 SYNOPSIS task "do-something", "server01", sub { on_rollback { rmdir "/tmp/mydata"; }; transaction { mkdir "/tmp/mydata"; upload "files/myapp.tar.gz", "/tmp/mydata"; run "cd /tmp/mydata; tar xzf myapp.tar.gz"; if($? != 0) { die("Error extracting myapp.tar.gz"); } }; }; =head1 EXPORTED FUNCTIONS =over 4 =cut package Rex::Transaction; { $Rex::Transaction::VERSION = '0.55.3'; } use strict; use warnings; require Exporter; use vars qw(@EXPORT @ROLLBACKS); use base qw(Exporter); use Rex::Logger; use Rex::TaskList; use Data::Dumper; @EXPORT = qw(transaction on_rollback); =item transaction($codeRef) Start a transaction for $codeRef. If $codeRef dies it will rollback the transaction. task "deploy", group => "frontend", sub { on_rollback { rmdir "..."; }; deploy "myapp.tar.gz"; }; task "restart_server", group => "frontend", sub { run "/etc/init.d/apache2 restart"; }; task "all", group => "frontend", sub { transaction { do_task [qw/deploy restart_server/]; }; }; =cut sub transaction(&) { my ($code) = @_; my $ret = 1; Rex::Logger::debug("Cleaning ROLLBACKS array"); @ROLLBACKS = (); Rex::TaskList->create()->set_in_transaction(1); eval { &$code(); }; if ($@) { Rex::Logger::info("Transaction failed. Rolling back."); $ret = 0; for my $rollback_code ( reverse @ROLLBACKS ) { # push the connection of the task back Rex::push_connection( $rollback_code->{"connection"} ); # run the rollback code &{ $rollback_code->{"code"} }(); # and pop it away Rex::pop_connection(); } die("Transaction failed. Rollback done."); } Rex::TaskList->create()->set_in_transaction(0); return $ret; } =item on_rollback($codeRef) This code will be executed if one step in the transaction fails. See I. =cut sub on_rollback(&) { my ($code) = @_; push( @ROLLBACKS, { code => $code, connection => Rex::get_current_connection() } ); } =back =cut 1;