NAME Perinci::Sub::Gen::Undoable - Generate undoable (transactional, dry-runnable, idempotent) function VERSION version 0.18 SYNOPSIS # See an example, like in Setup::File::Symlink DESCRIPTION This module helps you write undoable/transactional functions (as well as functions that support dry-run and are idempotent). SEE ALSO Rinci::function::Undo, Rinci::function::Transaction, Rinci Setup. DESCRIPTION This module has Rinci metadata. FUNCTIONS None are exported by default, but they are exportable. gen_undoable_func(%args) -> [status, msg, result, meta] Generate undoable (transactional, dry-runnable, idempotent) function. This function is basically a helper for writing undoable (as well as transactional, dry-runnable, and idempotent) function. This function will generate a function with the basic structure, and you supply the 'business-logic' bits through the 'build_steps' and 'steps' arguments. This generator helps because writing an undoable and transactional function is a bit tricky. This helper shields function writer from having to interact with the transaction manager, or writing the steps loop, or writing the rollback mechanism on his/her own, and just focus on writing the actual steps. Some notes: * Though it generally should not die(), generated function might still die, there is no big eval{} loop inside. But this is usually OK since a function wrapper (like Perinci::Sub::Wrapper) has this loop. For examples, see Setup::* Perl modules. Control flow: 1. "check_args" hook is executed, if supplied. It should return enveloped result. If response is not success, exit with this response. 1. If "-undo_action" argument is "do", "build_steps" hook is executed to get list of steps (an arrayref). If "-undo_action" is "undo" or "redo", steps is retrieved either from transaction manager ("-tx_manager" argument) or passed undo data ("-undo_data" argument). 1. Execute the steps. First, step's "check" hook is executed. If it returns undef, it means nothing needs to be done and we move on to the next step. If it returns an arrayref (undo step), it means we need to record the undo step first to transaction manager (if we are using transaction) or just collect the step in an array (if not using transaction), and then execute the step's "fix" hook. The hook should return an enveloped result. If response if not success, we trigger the rollback mechanism (see point 4). Otherwise we move on to the next step. After all the steps are executed successfully, we return 200 response. 1. To rollback: if we are not using transaction, we get out of the loop in point 3) and enter a loop to execute the undo steps in backward order (which is basically the same as point 3). If we are using transaction, we call transaction manager's rollback() (which will also essentially do the same kind of loop). If there is failure in the rollback steps, we just exit with the last step's response. Additional notes: * Generated function returns result as well as result metadata (3rd and 4th element of envelope array). Currently each step's "fix" hook is passed these two thus given the opportunity to fill/change them. Result is initially {} like result metadata. If result is still {} at the end of executing steps, "undef" is used instead. Arguments ('*' denotes required arguments): * args => *hash* (default: {}) Specification for generated function's arguments. This is just like the metadata property 'args'. * build_steps* => *array|code* Code to build steps. This is the code that should build the steps. Code will be given (\%args) and should return an enveloped response. If response is not a success one, function will exit with that response. Steps must be an array of steps, where each step is like this: [NAME, ...] (an array with step name as the first element and step argument(s) name, if any, in the rest of the elements). Each step must be defined in the "steps" argument. * check_args => *code* Code to check function's arguments. This is a hook to allow the generated function to check its arguments. This should later be mostly unnecessary when Perinci::Sub::Wrapper already integrates with Data::Sah to generate argument-checking code from schema. Code is given (\%args), where you can modify the args (e.g. set defaults, etc) and it will be carried on to the other steps like 'build_steps'. Code should return enveloped result. If response is not a success one, it will be used as the function's response. * description => *str* Generated function's description. * install => *bool* (default: 1) Whether to install generated function (and metadata). By default, generated function will be installed to the specified (or caller's) package, as well as its generated metadata into %SPEC. Set this argument to false to skip installing. * log_level_fix_step => *str* (default: "info") At what level to show log messages when performing step. By default, it is at "info" (can be turned on using --verbose or VERBOSE=1 in command-line scripts). For example: % VERBOSE=1 u-trash --dry-run *.bak [info] (DRY) Trashing file1.bak ... [info] (DRY) Trashing file2.bak ... [info] (DRY) Trashing file3.bak ... However, if you feel it is too chatty, you can lower it to 'trace', for example. * name* => *str* Generated function's name, e.g. `myfunc`. * package => *str* Generated function's package, e.g. `My::Package`. This is needed mostly for installing the function. You usually don't need to supply this if you set "install" to false. If not specified, caller's package will be used by default. * steps* => *hash* Steps specification. A step must at least have "check" and "fix" routines (or a single combined "check_and_fix" routine). * summary => *str* Generated function's summary. * trash_dir => *bool* (default: 0) Whether function needs undo trash directory. * tx => *hash* (default: {}) Whether function is transactional. Valid values include {use=>1} (meaning function can use transaction and will utilize it if given '-tx' special argument), {req=>1} (meaning function always require '-tx' and will return error response if not given it). Otherwise function will not use transaction, undo data will be passed to function via '-undo*data' special argument and returned by function in 'undo*data' result metadata. Return value: Returns an enveloped result (an array). First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information. AUTHOR Steven Haryanto COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Steven Haryanto. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. POD ERRORS Hey! The above document had some coding errors, which are explained below: Around line 639: You have '=item 1' instead of the expected '=item 2' Around line 648: You have '=item 1' instead of the expected '=item 3' Around line 662: You have '=item 1' instead of the expected '=item 4'