abw / Template2

Perl Template Toolkit v2
http://template-toolkit.org/
146 stars 94 forks source link

File cache isn't updated while a template is in memory #257

Open sewi-cpan opened 4 years ago

sewi-cpan commented 4 years ago

Reproduce: echo 'initial value' >test.tt perl -MTemplate -le '$tt = Template->new(COMPILE_EXT => ".ttc", COMPILE_DIR => "."); for (1..100) { system "ls -l test.tt test.tt.ttc"; $tt->process("test.tt"); sleep 3; }' Another shell: echo 'second value' >test.tt

What happens? initial value is shown until the template content changes, then second value is shown. The cache file test.tt.ttc still contains initial value after the change.

What should happen? The cache file should also be updated.

Why Based on 3.007, but also confirmed since 2.24: sub _fetch first checks if the requested template file is found within the memory cache of $self->{ LOOKUP }. Any template not found there is checked for an up-to-date cached version or the original version on disk which is compiled into the compiled version afterward. Any template found in the memory cache is regularly checked for file updates using _refresh. _refresh checks if the last check is older than STATS_TTL seconds and re-reads the mtime of the original template file if it should be re-checked. If the mtime of the original template now differs from the one stored in memory, the original template file is re-read using _load and compiled using _compile:

        if ( ! defined $template_mtime || ( $template_mtime != $slot->[ LOAD ] )) {
            $self->debug("refreshing cache file ", $slot->[ NAME ])
                if $self->{ DEBUG };

            ($data, $error) = $self->_load($slot->[ NAME ], $slot->[ DATA ]->{ name });
            ($data, $error) = $self->_compile($data)
                unless $error;

sub _compile does also write the disk cache, but only if the filename of the template in the disk cache is passed as the second argument - which is not. Once a new process (without the template memory cache) does read the template, it discovers the difference between the original file and disk cache file - and recompiles the template to a new disk cache file. That's why the problem never ends up in old template content being used.