NAME
    CHI::Cascade - a cache dependencies (cache and like 'make' utility
    concept)

SYNOPSIS
        use CHI;
        use CHI::Cascade;

        $cascade = CHI::Cascade->new(chi => CHI->new(...));

        $cascade->rule(
            target  => 'unique_name',
            depends => ['unique_name_other1', 'unique_name_other2'],
            code    => sub {
                my ($rule, $target_name, $values_of_depends) = @_;

                # $values_of_depends == {
                #     unique_name_other1 => $value_1,
                #     unique_name_other2 => $value_2
                # }
                # $rule->target     eq      $target_name
                # $rule->depends    ===     ['unique_name_other1', 'unique_name_other2']
                # $rule->dep_values ==      $values_of_depends
                # $rule->params     ==      { a => 1, b => 2 }

                # Now we can calcualte $value
                return $value;
            },
            params  => { a => 1, b => 2 }
        );

        $cascade->rule(
            target  => 'unique_name_other1',
            depends => 'unique_name_other3',
            code    => sub {
                my ($rule, $target_name, $values_of_depends) = @_;

                # $values_of_depends == {
                #     unique_name_other3 => $value_3
                # }

                # computing here
                return $value;
            }
        );

        $value_of_this_target = $cascade->run('unique_name');

DESCRIPTION
    This module is the attempt to use a benefits of caching and 'make'
    concept. If we have many an expensive tasks and want to cache it we can
    split its to small expsnsive tasks and to describe dependencies for
    cache items.

    This module is experimental yet. I plan to improve it near time but some
    things already work. You can take a look for t/* tests as examples.

CONSTRUCTOR
    $cascade = CHI::Cascade->new( %options )
        This method constructs a new "CHI::Cascade" object and returns it.
        Key/value pair arguments may be provided to set up the initial
        state. Now there is only one option: *chi* - instance of CHI object.

METHODS
    rule( %options )
        To add new rule to "CHI::Cascade" object. All rules should be added
        before first "run" method

        The keys of %options are:

        target
            A target for "run" and for searching of "depends". It can be as
            scalar text or "Regexp" object created through "qr//"

        depends
            The list or a scalar value of dependencies - the list of targets
            which the current rule is dependent. Each item can be scalar
            value (exactly matched target) or code reference which will be
            executed during matching of target. A code subroutine will get a
            parameters from "=~" operator against "target" matching by
            "qr//" operator(not tested while) - please see the section
            "EXAMPLE" for this example.

        code
            The code reference for computing a value of this target. Will be
            executed if no value in cache for this target or any dependence
            or dependences of dependences and so on will be recomputed. Will
            be executed as $code->( $rule, $target,
            $hashref_to_value_of_dependencies ) *(The API of running this
            code was changed since v0.10)*

            $rule
                An instance of CHI::Cascade::Rule object. You can use it
                object as accessor for some current executed target data
                (plain text of target, for getting of parameters and so on).
                Please to see CHI::Cascade::Rule

            $target
                A current target as plain text (what a target the $cascade
                got from run method)

            $hashref_to_value_of_dependencies
                A hash reference of values of all dependencies for current
                target. Keys in this hash are flat strings of dependecies
                and values are computed or cached ones.

                This module should guarantee that values of dependencies
                will be valid values even if value is "undef". This code can
                return "undef" value as a valid code return but author
                doesn't recommend it. If "CHI::Cascade" could not get a
                valid values of all dependencies of current target before
                execution of this code the last will not be executed (The
                "run" will return "undef").

        params
            You can pass in your code any additional parameters by this
            option. These parameters are accessed in your code through
            params method of CHI::Cascade::Rule instance object.

    run( $target )
        This method makes a cascade computing if need and returns value for
        this target If any dependence of this target of any dependencies of
        dependencies were recomputed this target will be recomputed too.

    touch( $target )
        This method refreshes the time of this target. Here is analogy with
        touch utility of Unix and behaviour as make after it. After "touch"
        all targets are dependent from this target will be recomputed at
        next "run" with an appropriate ones.

STATUS
    This module is experimental and not finished for new features ;-) Please
    send me issues through <https://github.com/Perlover/CHI-Cascade> page

CHI::Cascade & make
    Here simple example how it works. Here is a direct analogy to Unix make
    utility:

        In CHI::Cascade:            In make:

        rule                        rule
        depends                     prerequisites
        code                        commands
        run( rule_name )            make target_name

FEATURES
    The features of this module are following:

    Computing inside process
        If module needs to compute item for cache we compute inside process
        (no forks) For web applications it means that one process for one
        request could take a some time for computing. But other processes
        will not wait and will get either old previous computed value or
        *undef* value.

    Non-blocking computing for concurrent processes
        If other process want to get data from cache we should not block it.
        So concurrent process can get an old data if new computing is run or
        can get *undef* value. A concurrent process should decide itself
        what it should do after it - try again after few time or print some
        message like 'Please wait and try again' to user.

    Each target is splitted is two items in cache
        For optimization this module keeps target's info by separately from
        value item. A target item has lock & timestamp fields. A value item
        has a computed value.

EXAMPLE
    For example please to see the SYNOPSIS

    When we prepared a rules and a depends we can:

    If unique_name_other1 and/or unique_name_other2 are(is) more newer than
    unique_name the unique_name will be recomputed. If in this example
    unique_name_other1 and unique_name_other2 are older than unique_name but
    the unique_name_other3 is newer than unique_name_other1 then
    unique_name_other1 will be recomputed and after the unique_name will be
    recomputed.

    And even we can have a same rule:

        $cascade->rule(
            target  => qr/unique_name_(.*)/,
            depends => sub { 'unique_name_other_' . $_[0] },
            code    => sub {
                my ($rule, $target_name, $values_of_depends) = @_;

                # $rule->qr_params          === ( 3 )
                # $target_name              == 'unique_name_3' if $cascade->run('unique_name_3') was
                # $values_of_depends        == {
                #     unique_name_other_3   => $value_ref_3
                # }
            }
        );

        $cascade->rule(
            target  => qr/unique_name_other_(.*)/,
            code    => sub {
                my ($rule, $target_name, $values_of_depends) = @_;
                ...
            }
        );

    When we will do:

        $cascade->run('unique_name_52');

    $cascade will find rule with qr/unique_name_(.*)/, will make =~ and will
    find a depend as unique_name_other_52

AUTHOR
    This module has been written by Perlover <perlover@perlover.com>

LICENSE
    This module is free software and is published under the same terms as
    Perl itself.

SEE ALSO
    CHI::Cascade::Rule
        An instance of this object can be used in your target codes.

    CHI This object is used for cache.

    CHI::Driver::Memcached::Fast
        Recommended if you have the Memcached

    CHI::Driver::File
        Recommended if you want to use the file caching instead the
        Memcached for example

