2017-01-19 10 views
2

В настоящее время я разрабатываю небольшое одностраничное веб-приложение с использованием Mojolicious. Приложение имеет интерфейс Javascript (с использованием Backbone), который ведет переговоры с REST-ish API; макет источника примерно равен:Мозаичный кеш шаблона устарел

use Mojolicious::Lite; 

# ... setup code ... 

get '/' => sub { 
    my $c = shift; 
    # fetch+stash data for bootstrapped collections... 
    $c->render('app_template'); 
}; 

get '/api_endpoint' => sub { 
    my $c = shift; 
    # fetch appropriate API data... 
    $c->render(json => $response); 
}; 

# ... more API endpoints ... 

app->start; 

Шаблон приложения использует EP, но очень минимально; единственные серверные директивы шаблонов просто вставляют JSON для загрузочных коллекций. Он развертывается через Apache как простой сценарий CGI. (Это не оптимально, но для внутреннего использования с низким трафиком и более сложная конфигурация сервера является проблемой в контексте.) Perl CGI настроен через mod_perl.

Это работает большую часть времени, но иногда рендеринг каким-то образом понимает, что он должен кэшировать шаблон и игнорировать его изменения. В записях отладки в error_log показано «Рендеринг кэшированного шаблона», а не обычный «Шаблон рендеринга», и мои новые изменения в шаблоне перестают появляться в браузере. Я не могу найти надежный способ остановить это, хотя в конечном итоге он остановится сам по себе в соответствии с условиями, которые я не могу различить.

Как я могу сделать шаблон заметки приложения надежно? В качестве альтернативы, как можно полностью отключить кэширование шаблонов?

+0

Вы были со мной в _works большую часть time_. :) – simbabque

ответ

5

Как я могу сделать шаблон уведомления приложения надежно?

Это то, на что предназначен сервер разработки morbo. Morbo не будет использоваться для развертывания вашего реального кода, но для среды разработки, где вы постоянно меняете свой код и шаблоны. Как правило, изменения в живом коде и шаблонах предназначены для обработки путем перезапуска сервера приложений или Apache в вашем случае. (Hypnotoad имеет возможность горячего перезапуска для этой цели)

В качестве альтернативы, как можно полностью отключить кэширование шаблонов?

Чтобы сделать это, добавьте следующий код установки (вне трасс, после use Mojolicious::Lite):

app->renderer->cache->max_keys(0); 
+0

У меня была привычка делать развитие в этой среде без особого внимания; в теории это среда CGI, а это означает, что каждая новая загрузка страницы должна иметь свой собственный процесс.Я предполагаю, что mod_perl каким-то образом разбивает этот инвариант. Несмотря на это, отключается кеш. –

3

Для старого ответа см. Ниже.

Я включил результаты этого ответа в плагин и выпустил его на CPAN как Mojolicious::Plugin::Renderer::WithoutCache после обсуждения wit Grinnz на IRC, где они рекомендовали выпуск.

Вы можете использовать его как это:

use Mojolicious::Lite; 
plugin 'Renderer::WithoutCache'; 

Это создаст новый объект кэша, который ничего не делает, и установить, что во всем мире в визуализатор. Таким образом, его не нужно создавать каждый раз, как это сделал мой первоначальный ответ ниже.

Теоретически это должно быть быстрее, чем Grinnz' approach (что более разумно), и поскольку вы явно не хотите кэшировать, вы, очевидно, хотите, чтобы все было как можно быстрее, не так ли? Вероятно, это быстрее, потому что реальный Mojo :: Cache все равно должен пойти и попытаться установить кеш, но затем прервать, потому что свободных ключей нет, и он также будет пытаться каждый раз искать значения из кеша.

Я сравнивал это как с Dumbbench, так и с Benchmark. Оба они показали незначительные результаты. Я запускал их каждый раз пару раз, но они менялись много, и не ясно, какой из них быстрее. Я включил вывод run, где моя реализация была быстрее, но она по-прежнему показывает, насколько незначительна разница.

Benchmark с Dumbbench:

use Dumbbench; 
use Mojolicious::Renderer; 
use Mojolicious::Controller; 
use Mojolicious::Plugin::Renderer::WithoutCache::Cache; 

my $controller   = Mojolicious::Controller->new; 
my $renderer_zero_keys = Mojolicious::Renderer->new; 
$renderer_zero_keys->cache->max_keys(0); 

my $renderer_nocache = Mojolicious::Renderer->new; 
$renderer_nocache->cache(Mojolicious::Plugin::Renderer::WithoutCache::Cache->new); 

my $bench = Dumbbench->new(
    target_rel_precision => 0.005, 
    initial_runs   => 5000, 
); 

$bench->add_instances(
    Dumbbench::Instance::PerlSub->new(
     name => 'max_keys', 
     code => sub { 
      $renderer_zero_keys->render($controller, { text => 'foobar' }); 
     } 
    ), 
    Dumbbench::Instance::PerlSub->new(
     name => 'WithoutCache', 
     code => sub { 
      $renderer_nocache->render($controller, { text => 'foobar' }); 
     } 
    ), 
); 

$bench->run; 
$bench->report; 

__END__ 
max_keys: Ran 8544 iterations (3335 outliers). 
max_keys: Rounded run time per iteration: 5.19018e-06 +/- 4.1e-10 (0.0%) 
WithoutCache: Ran 5512 iterations (341 outliers). 
WithoutCache: Rounded run time per iteration: 5.0802e-06 +/- 5.6e-09 (0.1%) 

Benchmark с Benchmark:

use Benchmark 'cmpthese'; 
use Mojolicious::Renderer; 
use Mojolicious::Controller; 
use Mojolicious::Plugin::Renderer::WithoutCache::Cache; 

my $controller   = Mojolicious::Controller->new; 
my $renderer_zero_keys = Mojolicious::Renderer->new; 
$renderer_zero_keys->cache->max_keys(0); 

my $renderer_nocache = Mojolicious::Renderer->new; 
$renderer_nocache->cache(Mojolicious::Plugin::Renderer::WithoutCache::Cache->new); 

cmpthese(
    -5, 
    { 
     'max_keys' => sub { 
      $renderer_zero_keys->render($controller, { text => 'foobar' }); 
     }, 
     'WithoutCache' => sub { 
      $renderer_nocache->render($controller, { text => 'foobar' }); 
     }, 
    } 
); 

__END__ 
       Rate  max_keys WithoutCache 
max_keys  190934/s   --   -2% 
WithoutCache 193846/s   2%   -- 

я Recon в тяжелой среде нагрузки с большим количеством вызовов, это в конечном счете сделать разницу, но очень трудно доказать. Поэтому, если вам не нравится думать о внутренних элементах кеша, этот плагин может быть полезен.


Старый ответ:

Глядя на Mojolicious::Plugin::EPRenderer я узнал, что есть cache. Это пример Mojo::Cache, который имеет методы get, set и max_keys и наследует от Mojo::Base (как, вероятно, все в Mojolicious).

::EPRenderer gets a $renderer, который является Mojolicious::Renderer. Он содержит экземпляр Mojo :: Cache. Я посмотрел на $c с Data::Printer и узнал, что есть $c->app, который содержит все те.

Зная это, вы можете легко создать свой собственный класс кеша, который ничего не делает.

package Renderer::NoCache; 
use Mojo::Base -base; 

sub get {} 
sub set {} 
sub max_keys {} 

Теперь вы вставляете его в $c.

package Foo; 
use Mojolicious::Lite; 

get '/' => sub { 
    my $c = shift; 

    $c->app->renderer->cache(Renderer::NoCache->new); 

    $c->render(template => 'foo', name => 'World'); 
}; 

app->start; 

__DATA__ 

@@ foo.html.ep 
Hello <%= $name =%>. 

Теперь любая попытка get или set кэш просто ничего не делает. Он будет пытаться кэшировать, но он никогда не найдет ничего.

Конечно, это не здорово создавать новый объект каждый раз. Было бы лучше сделать этот объект один раз при запуске и получить его во внутренней постоянной версии app. У вас есть CGI, так что это может не изменить ситуацию.


Вы также можете просто обезьяна пропатчить get из Mojo::Cache. Это более Hacky подход будет делать то же самое:

package Foo; 
use Mojolicious::Lite; 

*Mojo::Cache::get = sub { }; 

get '/' => sub { 
    my $c = shift; 

    $c->render(template => 'foo', name => 'World'); 
}; 

app->start; 

Но остерегайтесь: мы просто отключить выборку из каждый кэш в приложении, которое использует Mojo :: Cache. Возможно, это не то, что вы хотите.