Rinci::Undo man page on Hurd

Man page or keyword search:  
man Server   6387 pages
apropos Keyword Search (all sections)
Output format
Hurd logo
[printable version]

Rinci::Undo(3pm)      User Contributed Perl Documentation     Rinci::Undo(3pm)

NAME
       Rinci::Undo - (DEPRECATED) Protocol for undo operations in functions

VERSION
       version 1.1.43

SPECIFICATION VERSION
	1.1

STATUS
       This protocol (riundo for short) is now deprecated in favor of
       Rinci::Transaction (ritx for short) for several reasons:

       ·   riundo is inherently unreliable

	   Undo information is returned by function after the function has
	   performed the action. If function dies in the middle of action,
	   client does not have the information to undo the (partially
	   completed) action. That is why in ritx, the TM asks the function
	   first for undo information before asking the function to perform
	   its action.

       ·   ritx does not limit using the same function for undo

	   In riundo, we must call the same function (passing the previously
	   obtained undo data from the that function) to undo the information.
	   This is sometimes slightly cumbersome. The undo action might be
	   provided by other functions, but we still have to go through the
	   same function first.

       ·   ritx can also implement undo/redo

	   So there is no need for maintaining two specifications.

SPECIFICATION
       This document describes the Rinci undo protocol. This protocol must be
       followed by functions that claim that they support undo (have their
       "undo" "feature" set to true). Such functions are from here on called
       undoable function (or just function, unless when ambiguous).

       The protocol is basically the non-OO version of the command pattern, a
       design pattern most commonly used to implement undo/redo functionality.
       In this case, each function behaves like a command object. You pass a
       special argument "-undo_action" with the value of "do" and "undo" to
       execute or undo a command, respectively. For "do" and "undo", the same
       set of arguments are passed.

   Requirements
       Function MUST check special argument "-undo_action" before it checks
       other arguments. Function MUST at least support the following undo
       action: "do", "undo". On unsupported/unknown undo action, function MUST
       return status 400, with message like "Unsupported undo action".

       If "-undo_action" is not set, it means caller does not care about undo.
       Undoable function should execute as any normal function.

   Performing 'do'
       To indicate that we need undo, we call function by passing special
       argument "-undo_action" with the value of "do". Function should perform
       its operation and save undo data along the way. If "-undo_action" is
       not passed or false/undef, function should assume that caller does not
       need undo later, so function need not save any undo data. After
       completing operation successfully, function should return status 200,
       the result, and undo data. Undo data is returned in the result metadata
       (the fourth element of result envelope), example:

	[200, "OK", $result, {undo_data=>$undo_data}]

       Undo data should be serializable so it is easy to be made persistent if
       necessary (e.g. by some undo/transaction manager).

   Performing 'undo'
       To perform an undo, caller must call the function again with the same
       previous arguments, except "-undo_action" should be set to "undo" and
       "-undo_data" set to undo data previously given by the function.
       Function should perform the undo operation using the undo data. Upon
       success, it must return status 200, the result, and an undo data (in
       other words, redo data, since it can be used to undo the undo
       operation).

   Performing 'redo'
       To perform redo, caller can call the function again with <-undo_action>
       set to "undo" and "-undo_data" set to the redo data given in the undo
       step. Or, alternatively, caller can just perform a normal do (see
       above).

       An example:

	$SPEC{setenv} = {
	    v => 1.1,
	    summary  => 'Set environment variable',
	    args     => {
		name  => {req=>1, schema=>'str*'},
		value => {req=>1, schema=>'str*'},
	    },
	    features => {undo=>1},
	};
	sub setenv {
	    my %args	    = @_;
	    my $name	    = $args{name};
	    my $value	    = $args{value};
	    my $undo_action = $args{-undo_action} // '';
	    my $undo_data   = $args{-undo_data};

	    my $old;
	    if ($undo_action) {
		# save original value and existence state
		$old = [exists($ENV{$name}), $ENV{$name}];
	    }

	    if ($undo_action eq 'undo') {
		if ($undo_data->[0]) {
		    $ENV{$name} = $undo_data->[1];
		} else {
		    delete $ENV{$name};
		}
	    } else {
		$ENV{$name} = $value;
	    }

	    [200, "OK", undef, $undo_action ? {undo_data=>$old} : {}];
	}

       The above example declares an undoable command "setenv" to set an
       environment variable (%ENV).

       To perform command:

	my $res = setenv(name=>"DEBUG", value=>1, -undo_action=>"do");
	die "Failed: $res->[0] - $res->[1]" unless $res->[0] == 200;
	my $undo_data = $res->[3]{undo_data};

       To perform undo:

	$res = setenv(name=>"DEBUG", value=>1,
		      -undo_action="undo", -undo_data=>$undo_data);
	die "Can't undo: $res->[0] - $res->[1]" unless $res->[0] == 200;

       After this undo, DEBUG environment variable will be set to original
       value. If it did not exist previously, it will be deleted.

       To perform redo:

	my $redo_data = $res->[3]{undo_data};
	$res = setenv(name=>"DEBUG", value=>1,
		      -undo_action="undo", -undo_data=>$redo_data);

       or you can just do:

	$res = setenv(name=>"DEBUG", value=>1, -undo_action="do");

   Saving undo data in external storage
       Although the complete undo data can be returned by the function in the
       "undo_data" result metadata property, sometimes it is more efficient to
       just return a pointer to said undo data, while saving the actual undo
       data in some external storage.

       For example, if a function deletes a big file and wants to save undo
       data, it is more efficient to move the file to trash directory and
       return its path as the undo data, instead of reading the whole file
       content and its metadata to memory and return it in "undo_data" result
       metadata.

       Functions which require undo trash directory should specify this in its
       metadata, through the "undo_trash_dir" dependency clause. For example:

	deps => {
	    ...
	    trash_dir => 1,
	}

       When calling function, caller needs to provide path to undo trash
       directory via special argument "-trash_dir", for example:

	-trash_dir => "/home/.trash/2fe2f4ad-a494-0044-b2e0-94b2b338056e"

   What about non-undoable actions?
       Like in real life, not all actions are undoable. Examples of
       undoable/irreversible actions include wiping a file/directory (more
       generally speaking, any action to permanently delete/destroy something,
       without backing up the data first), sending an email (more generally
       speaking, any action that is sent to an external entity beyond our
       control, unless that external entity provides a way to undo the
       action).

       An undoable function MUST NOT mix undoable and non-undoable actions.
       For example:

	safe_delete(file=>'/path/to/file'); # puts file into Trash, undoable action
	safe_delete(file=>'/path/to/file', permanent=>1); # deletes file, non-undoable

       The "safe_delete" function above mixes undoable action (putting a file
       into Trash directory) and non-undoable action (permanently deleting a
       file without putting it in Trash). Without domain knowledge of the
       function, a caller cannot know whether a call will be undoable or not.
       This will also prevent the function from participating in a
       transaction, because transaction requires function call to always be
       undoable, for rollback purpose.

       The solution is to separate non-undoable action in another function,
       for example:

	trash(file=>'/path/to/file');  # undoable, can execute inside transaction
	delete(file=>'/path/to/file'); # non-undoable, executes outside transaction
	empty_trash();		       # non-undoable, executes outside transaction

       The non-undoable function is also non-transactional (it operates
       outside the scope of a transaction). But it can still be idempotent.
       And it can manipulate the transactions if it needs too. In the example,
       the empty_trash() function instructs the transaction manager to discard
       the trash() transactions, since after the trash is emptied, the trash()
       transactions cannot be undone anyway.

SEE ALSO
       Related specifications: Rinci::Transaction

HOMEPAGE
       Please visit the project's homepage at
       <https://metacpan.org/release/Rinci>.

SOURCE
       Source repository is at <https://github.com/sharyanto/perl-Rinci>.

BUGS
       Please report any bugs or feature requests on the bugtracker website
       <https://rt.cpan.org/Public/Dist/Display.html?Name=Rinci>

       When submitting a bug or request, please include a test-file or a patch
       to an existing test-file that illustrates the bug or desired feature.

AUTHOR
       Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE
       This software is copyright (c) 2013 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.

perl v5.18.1			  2013-12-25		      Rinci::Undo(3pm)
[top]

List of man pages available for Hurd

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net