App-Task

 view release on metacpan or  search on metacpan

lib/App/Task.pm  view on Meta::CPAN


App::Task - Nest tasks w/ indented output and pre/post headers

=head1 VERSION

This document describes App::Task version 0.03

=head1 SYNOPSIS

    use App::Task;

    task "…" => sub {};
    task "…" => ["system","args","here"], {fatal => 1};
    task "…" => "system command here";

Nested

    task "…" => sub {
        task "…" => sub {
            task "…" => sub { … };
        };
        task "…" => sub { … };
        task "…" => sub {
            task "…" => sub {
                task "…" => sub { …  };
            };
        };
    }

=head1 DESCRIPTION

This allows us to create scripts that organize tasks together and have their output be organized similarly and with added clarity.

It does this by wrapping each task in a starting/ending output line, indenting output congruent with nested C<task()> depth.

For example, say this:

    system(…);
    foo();
    system(…,…);
    say test_foo() ? "foo is good" : "foo is down";

outputs this:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit amet.
    Facilisi morbi tempus iaculis urna id volutpat lacus laoreet.
    Ullamcorper eget nulla facilisi etiam dignissim diam.
    Maecenas volutpat blandit aliquam etiam erat velit scelerisque in dictum.
    foo is good

Nothing wrong with that but it could be easier to process visually, so if we C<task()>’d it up a bit like this:

    task "setup foo" => sub {
        task "configure foo" => "…";
        task "run foo" => \&foo;
    };

    task "finalize foo" => sub {
        task "enable barring" => […,…];
        task "verify foo" => sub {
            my $status = test_foo();
            say $status ? "foo is good" : "foo is down";
            return $status;
        };
    };

Now you get:

    ➜➜➜➜ [1.1] setup foo …
        ➜➜➜➜ [2.1] configure foo …
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
         … done (configure foo).

        ➜➜➜➜ [2.2] run foo …
            Nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit amet.
            Facilisi morbi tempus iaculis urna id volutpat lacus laoreet.
         … done (run foo).

     … done (setup foo).

    ➜➜➜➜ [1.2] finalize foo …
        ➜➜➜➜ [2.1] enable barring …
            Ullamcorper eget nulla facilisi etiam dignissim diam.
            Maecenas volutpat blandit aliquam etiam erat velit scelerisque in dictum.
         … done (enable barring).

        ➜➜➜➜ [2.2] verify foo …
            foo is down
         … failed (verify foo).

     … done (finalize foo).

=head1 INTERFACE

Each variant has a pre/post heading and indented output.

=head2 task NAME => CODEREF

If CODEREF returns true the post heading will be “done”, if it returns false it will be “failed”.

To make CODEREF fatal just throw an exception.

=head2 task NAME => CMD_STRING

CMD_STRING is a string suitable for C<system(CMD_STRING)>.

If the command exits clean the post heading will be “done”, if it exits unclean it will be “failed”.

To make CMD_STRING exiting unclean be fatal you can set fatal to true in the optional 3rd argument to task:

    task "prep fiddler" => "/usr/bin/fiddler prep"; # will continue on unclean exit
    task "create fiddler" => "/usr/bin/fiddler new", { fatal => 1 }; # will die on unclean exit

=head2 task NAME => CMD_ARRAYREF

task NAME => CMD_ARRAYREF is a string suitable for C<system(@{CMD_ARRAYREF})>.

If the command exits clean the post heading will be “done”, if it exits unclean it will be “failed”.

To make CMD_STRING exiting unclean be fatal you can set fatal to true in the optional 3rd argument to task:

    task "prep fiddler" => ["/usr/bin/fiddler", "prep"]; # will continue on unclean exit
    task "create fiddler" => ["/usr/bin/fiddler", "new"], { fatal => 1 }; # will die on unclean exit

=head3 $ENV{App_Task_DRYRUN}

If this is true the C<CMD_ARRAYREF> and C<CMD_STRING> version of C<task()> will out put a DEBUG string of the command it would have run.

You can then check it in your application’s code to do things differently in a dry run mode. An example is found in the L</App::Task::tie_task()> example function below.

=head2 App::Task::tie_task()

Not exported or exportable.

Take no arguments. Returns the tied() objects for STDOUT, STDERR.

    App::Task::tie_task();
    my ($o, $e) = App::Task::tie_task();

Dies if you call it and STDOUT or STDERR are already tied.

Some modules don’t play well with tied STDOUT/STDERR. To get them to work you need to do some wrapping to essentially:

redefine the thing in question to do this pseudo code logic:

    if (SDTDOUT/STDERR are tied) {
        untie STDOUT/STDERR
        do the original thing
        reset STDOUT/STDERR by calling C<App::Task::tie_task()>



( run in 2.735 seconds using v1.01-cache-2.11-cpan-13bb782fe5a )