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 ($target_name, $values_of_depends) = @_;

               # $values_of_depends == {
               #     unique_name_other1 => $value_1,
               #     unique_name_other2 => $value_2
               # }

               # Now we can calcualte $value
               return $value;
           }
       );

       $cascade->rule(
           target  => 'unique_name_other1',
           depends => 'unique_name_other3',
           code    => sub {
               my ($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. This
           subroutine will get parameters: $_[0] - flat text of current
           target and hashref of values of dependencies. 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").

   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 ($target_name, $values_of_depends) = @_;

               # $this_name == 'unique_name_3' if $cascade->run('unique_name_3') was
               # $values_of_depends == {
               #     unique_name_other3 => $value_ref_3
               # }
           }
       );

       $cascade->rule(
           target  => qr/unique_name_other_(.*)/,
           code    => sub {
               my ($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 <[email protected]>

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

SEE ALSO
   CHI - mandatory
   CHI::Driver::Memcached::Fast - recommended
   CHI::Driver::File - file caching