perl-chi
perl-chi copied to clipboard
Add `no_defaults_for' attribute to fix subcache get/set infinite recursion
CHI subclasses that define one or more subcaches using defaults
, namespace
, or storage
are susceptible to infinite recursion upon get
and set
. Consider l1_loop.pl
:
#!/usr/bin/env perl
use strict;
use warnings;
package My::CHI;
use base 'CHI';
__PACKAGE__->config({
storage => {
local_file => {
driver => 'File',
root_dir => '/tmp/mychi',
},
raw_memory => {
driver => 'RawMemory',
global => 0,
},
},
defaults => {
storage => 'local_file',
l1_cache => {
storage => 'raw_memory',
},
},
});
package main;
my $cache = My::CHI->new;
$cache->set('it', 'off');
$ ./l1_loop.pl
Deep recursion on subroutine "Role::Tiny::_COMPOSABLE::CHI::Driver::Role::HasSubcaches::set" at /home/matt/git/perl-chi/lib/CHI/Driver/Role/HasSubcaches.pm line 88.
Deep recursion on anonymous subroutine at (eval 42) line 16.
^C
The reason is that the subcache is instantiated using the same defaults as the parent cache, so will have its own subcache, which has its own subcache, which has its own subcache, all the way down. This manifests as recursion on the anonymous subroutine
s defined with before
and around
in CHI::Driver::Role::HasSubcaches
.
This pull requests addresses the infinite recursion issue by adding the constructor param no_defaults_for
, which allows specifying a list of keys to delete from the defaults
, namespace
, and storage
hashrefs prior to instantiating a CHI subclass instance. All subcaches get l1_cache
and mirror_cache
automatically appended to no_defaults_for
-- only the parent cache can have subcaches defined from package defaults.
Thanks in advance for considering this pull request!
P.S.: I got the following error when running dzil build
:
$ dzil build
Can't call method "content" on an undefined value at /home/matt/opt/perl5/perlbrew/perls/perl-5.20.0/lib/site_perl/5.20.0/Dist/Zilla/Plugin/MakeMaker.pm line 318.
I fixed this by editing dist.ini
to remove filenames = Makefile.PL
from [PruneFiles]
and add exclude_filename = Makefile.PL
to [GatherDir]
. The real culprit might be some environment muck-up on my part -- please let me know :).