CHI-Cascade

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
Key/value pair arguments may be provided to set up the initial state.
Options are:
 
chi Required. Instance of CHI object. The CHI::Cascade doesn't construct
    this object for you. Please create instance of "CHI" yourself.
 
busy_lock
    Optional. Default is *never*. *This is not "busy_lock" option of
    CHI!* This is amount of time (to see "DURATION EXPRESSIONS" in CHI)
    until all target locks expire. When a target is to being computing
    it is locked. If process which is to be computing target and it will
    die or OS will be hangs up we can dead locks and locked target will
    never recomputed again. This option helps to avoid it. You can set
    up a special busy_lock for rules too.
 
target_chi
    Optional. This is CHI cache for target markers. Default value is
    value of "chi" option. It can be useful if you use a "l1_cache" in
    CHI option. So you can separate data of targets from target markers
    - data will be kept in a file cache and a marker in memory cache for
    example.

README  view on Meta::CPAN

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    Optional. You can pass in your code any additional parameters by
    this option. These parameters are accessed in your rule's code
    through "params" in CHI::Cascade::Rule method of
    CHI::Cascade::Rule instance object.
 
busy_lock
    Optional. Default is "busy_lock" of constructor or *never* if
    first is not defined. *This is not "busy_lock" option of CHI!*
    This is amount of time (to see "DURATION EXPRESSIONS" in CHI)
    until target lock expires. When a target is to being computed it
    is locked. If process which to be recomputing a target and it
    will die or OS will be hangs up we can dead locks and locked
    target will never recomputed again. This option helps to avoid
    it.
 
recomputed
    Optional. This is a computational callback (coderef). If target
    of this rule was recomputed this callback will be executed right
    away after a recomputed value has been saved in cache. The
    callback will be executed as $coderef->( $rule, $target, $value
    ) where passed parameters are:

lib/CHI/Cascade.pm  view on Meta::CPAN

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    }
    else {
        croak qq{The rule's target "$rule->{target}" is unknown type};
    }
}
 
sub target_computing {
    my $trg_obj;
 
    ( $trg_obj = $_[0]->{target_chi}->get("t:$_[1]") )
      ? ( ( ${ $_[2] } = $trg_obj->ttl ), $trg_obj->locked ? 1 : 0 )
      : 0;
}
 
sub target_is_actual {
    my ( $self, $target, $actual_term ) = @_;
 
    my $trg_obj;
 
    ( $trg_obj = $self->{target_chi}->get("t:$target") )
      ? $trg_obj->is_actual( $actual_term )

lib/CHI/Cascade.pm  view on Meta::CPAN

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
      if ($value);
 
    CHI::Cascade::Value->new( state => CASCADE_NO_CACHE );
}
 
sub target_lock {
    my ( $self, $rule ) = @_;
 
    my $target = $rule->target;
 
    # If target is already locked - a return
    return
      if ( $self->target_locked( $rule ) );
 
    my $trg_obj;
    $trg_obj = CHI::Cascade::Target->new
      unless ( ( $trg_obj = $self->{target_chi}->get("t:$target") ) );
 
    $trg_obj->lock;
    $self->{target_chi}->set( "t:$target", $trg_obj, $rule->target_expires( $trg_obj ) );
 
    $rule->{run_instance}{target_locks}{$target} = 1;
}

lib/CHI/Cascade.pm  view on Meta::CPAN

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
sub touch {
    my ( $self, $target ) = @_;
 
    if ( my $trg_obj = $self->{target_chi}->get("t:$target") ) {
        $trg_obj->touch;
        $self->{target_chi}->set( "t:$target", $trg_obj, $self->find( $target )->target_expires( $trg_obj ) );
    }
}
 
sub target_locked {
    my ( $self, $rule ) = @_;
 
    exists $rule->{run_instance}{target_locks}{ $rule->target };
}
 
sub recompute {
    my ( $self, $rule, $target, $dep_values) = @_;
 
    die CHI::Cascade::Value->new( state => CASCADE_DEFERRED )
      if $rule->{run_instance}{run_opts}{defer};

lib/CHI/Cascade.pm  view on Meta::CPAN

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
        die $exception;
    }
 
    return $ret;
};
 
$self->target_lock($rule)
  if ! $self->target_time($target);
 
$should_be_recomputed = $self->target_locked($rule);
 
if ( defined $ttl && $ttl > 0 && ! $should_be_recomputed ) {
    $ret_state = CASCADE_TTL_INVOLVED;
    $run_instance->{ttl} = $ttl;
}
else {
    my (
        $rule_ttl,
        $circle_hash,
        $start_time,

lib/CHI/Cascade.pm  view on Meta::CPAN

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
                delete $run_instance->{ $circle_hash }{$target}{$dep_target};
            }
 
            if ( defined $min_start_time ) {
                $ret_state = CASCADE_TTL_INVOLVED;
                $self->target_start_ttl( $rule, $min_start_time );
                $run_instance->{ttl} = $min_start_time + $rule_ttl - Time::HiRes::time;
            }
        }
 
        if ( $self->target_locked($rule) ) {
            # We should recompute this target
            # So we should recompute values for other dependencies
            foreach $dep_target (keys %dep_values) {
                if (   ! defined $dep_values{$dep_target}->[1]
                    || ! $dep_values{$dep_target}->[1]->is_value )
                {
                    $self->{stats}{dependencies_lookup}++;
                    $catcher->( sub {
                        if ( ! ( $dep_values{$dep_target}->[1] = $self->value_ref_if_recomputed( $dep_values{$dep_target}->[0], $dep_target, 1 ) )->is_value ) {
                            $self->target_remove($dep_target);
                            return 1;
                        }
                        return 0;
                    } ) == 1 && return undef;
                }
            }
        }
 
        return $self->recompute( $rule, $target, { map { $_ => $dep_values{$_}->[1]->value } keys %dep_values } )
          if $self->target_locked($rule);
 
        return CHI::Cascade::Value->new( state => $ret_state );
    };
 
    pop @{ $run_instance->{target_stack} };
 
    my $e = $@;
 
    if ( $self->target_locked($rule) ) {
        $self->target_unlock( $rule, $ret );
    }
    elsif ( $run_instance->{run_opts}{actual_term} && ! $only_from_cache && $run_instance->{orig_target} eq $target ) {
        $self->target_actual_stamp( $rule, $ret );
    }
 
    die $e if $e;
 
    return $ret || CHI::Cascade::Value->new;
}

lib/CHI/Cascade.pm  view on Meta::CPAN

551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
=item chi
 
B<Required>. Instance of L<CHI> object. The L<CHI::Cascade> doesn't construct this
object for you. Please create instance of C<CHI> yourself.
 
=item busy_lock
 
B<Optional>. Default is I<never>. I<This is not C<busy_lock> option of CHI!>
This is amount of time (to see L<CHI/"DURATION EXPRESSIONS">) until all target
locks expire. When a target is to being computing it is locked. If process which
is to be computing target and it will die or OS will be hangs up we can dead
locks and locked target will never recomputed again. This option helps to avoid
it. You can set up a special busy_lock for rules too.
 
=item target_chi
 
B<Optional>. This is CHI cache for target markers. Default value is value of
L</chi> option. It can be useful if you use a L<CHI/l1_cache> option. So you can
separate data of targets from target markers - data will be kept in a file cache
and a marker in memory cache for example.
 
=back

lib/CHI/Cascade.pm  view on Meta::CPAN

711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
B<Optional>. You can pass in your code any additional parameters by this option.
These parameters are accessed in your rule's code through
L<CHI::Cascade::Rule/params> method of L<CHI::Cascade::Rule> instance object.
 
=item busy_lock
 
B<Optional>. Default is L</busy_lock> of constructor or I<never> if first is not
defined. I<This is not C<busy_lock> option of CHI!> This is amount of time (to
see L<CHI/"DURATION EXPRESSIONS">) until target lock expires. When a target is
to being computed it is locked. If process which to be recomputing a target and
it will die or OS will be hangs up we can dead locks and locked target will
never recomputed again. This option helps to avoid it.
 
=item recomputed
 
B<Optional>. This is a computational callback (coderef). If target of this rule
was recomputed this callback will be executed right away after a recomputed
value has been saved in cache. The callback will be executed as $coderef->(
$rule, $target, $value ) where passed parameters are:
 
=over

lib/CHI/Cascade/Rule.pm  view on Meta::CPAN

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    if (@_) {
        $self->{value_expires} = $_[0];
        return $self;
    }
    ( ref $self->{value_expires} eq 'CODE' ? $self->{value_expires}->( $self ) : $self->{value_expires} ) // 'never';
}
 
sub target_expires {
    my ( $self, $trg_obj ) = @_;
 
    $trg_obj->locked
        ?
        $self->{busy_lock} || $self->{cascade}{busy_lock} || 'never'
        :
        $trg_obj->expires // $trg_obj->expires( $self->value_expires );
}
 
sub ttl {
    my $self = shift;
 
    return undef

lib/CHI/Cascade/Target.pm  view on Meta::CPAN

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 
sub new {
    my ($class, %opts) = @_;
 
    bless { %opts }, ref($class) || $class;
}
 
sub lock {
    $_[0]->{locked} = $$;
}
 
sub locked {
    exists $_[0]->{locked}
      and $_[0]->{locked};
}
 
sub unlock {
    delete $_[0]->{locked};
}
 
sub time {
    $_[0]->{time} || 0;
}
 
sub touch {
    $_[0]->{time} = Time::HiRes::time;
    delete $_[0]->{finish_time};
    delete $_[0]->{expires_finish_time};



( run in 0.477 second using v1.01-cache-2.11-cpan-a9ef4e587e4 )