2017-01-19 41 views
2

我目前正在開發一個使用Mojolicious的小型單頁Web應用程序。該應用程序有一個Javascript前端(使用Backbone),與REST-ish API進行對話;源的佈局大致是:Mojolicious模板緩存已過時

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

對於舊的答案見下文。

我把這個答案的調查結果爲插件和IRC,他們鼓勵釋放討論機智Grinnz後發佈在CPAN爲Mojolicious::Plugin::Renderer::WithoutCache

您可以使用它像這樣:

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

這將創建一個新的緩存對象,不執行任何操作,並安裝到全球的渲染器。這樣,它不需要每次都像我下面的初步答案一樣創建。

理論上,這應該比Grinnz' approach更快(這更明智),並且由於您明確不想緩存,所以您顯然希望事情儘可能快,對嗎?它應該更快,因爲真正的Mojo :: Cache仍然需要去嘗試設置緩存,但是會因爲沒有更多空閒密鑰而中止,並且它會嘗試每次從緩存中查找值。

我用DumbbenchBenchmark作爲基準。他們兩人都顯示了微不足道的結果。我幾次跑了他們,但他們波動很大,並且不清楚哪一個更快。我將執行速度更快的運行輸出包括在內,但它仍然表明差異是微乎其微的。

基準與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%) 

基準與基準:

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%   -- 

我在高負載環境中偵察,有很多電話的它最終將有所作爲,但很難證明。所以如果你不喜歡考慮緩存的內部,這個插件可能會有用。


老答案:

看着Mojolicious::Plugin::EPRenderer我發現有一個cache。這是一個Mojo::Cache實例,它有方法getsetmax_keys,並繼承Mojo::Base(如可能一切都在Mojolicious)。

::EPRenderer gets a $renderer的,這是一個Mojolicious::Renderer。它擁有Mojo :: Cache實例。我看着$cData::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 =%>. 

現在千方百計getset緩存乾脆什麼都不做。它會嘗試緩存,但它永遠不會找到任何東西。

當然這不是很大,每次做一個新的對象。最好在啓動時創建一個對象,並將其放入內部永久版本app。你有CGI,所以它可能沒有什麼區別。


你也只猴子修補getMojo::Cache。這種更哈克的方式將做同樣的事情:

package Foo; 
use Mojolicious::Lite; 

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

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

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

app->start; 

但要注意:我們剛剛從禁止在應用程序中每個緩存使用魔::緩存讀取。這可能不是你想要的。