Le cache du modèle Mojolicious est périmé

Je développe actuellement une petite application Web d’une seule page utilisant Mojolicious. L’application dispose d’une interface Javascript (utilisant Backbone) qui communique avec une API REST-ish; la mise en page de la source est grosso modo:

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; 

Le modèle d’application utilise EP, mais très minimalement; les seules directives de modèle côté serveur insèrent simplement JSON pour les collections bootstrap. Il est déployé via Apache en tant que script CGI simple. (Ce n’est pas optimal, mais c’est pour un usage interne à faible trafic, et une configuration de serveur plus complexe est problématique en contexte.) CGI Perl est configuré via mod_perl .

Cela fonctionne la plupart du temps, mais de temps en temps, le moteur de rendu a en quelque sorte l’idée qu’il doit mettre en cache le modèle et ignorer les modifications apscopes. Les enregistrements de débogage dans error_log affichent “Rendu le modèle en cache” plutôt que le “modèle de rendu” normal, et mes nouvelles modifications apscopes au modèle cessent d’apparaître dans le navigateur. Je ne peux pas trouver un moyen fiable d’arrêter cela, même s’il finira par s’arrêter tout seul selon les conditions que je ne peux pas discerner.

Comment puis-je modifier le modèle de notification d’application de manière fiable? Comment puis-je désactiver complètement la mise en cache des modèles?

Comment puis-je modifier le modèle de notification d’application de manière fiable?

C’est ce à quoi sert le serveur de développement morbo . Morbo ne serait pas utilisé pour votre déploiement de code en direct, mais pour un environnement de développement dans lequel vous modifiez continuellement votre code et vos modèles. Généralement, les modifications apscopes au code en direct et aux modèles sont censées être gérées en redémarrant le serveur d’applications ou Apache dans votre cas. ( Hypnotoad a une capacité de redémarrage à chaud à cette fin)

Comment puis-je désactiver complètement la mise en cache des modèles?

Pour ce faire, ajoutez le code d’installation suivant (en dehors des routes, après use Mojolicious::Lite ):

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

Pour les anciennes réponses, voir ci-dessous.

J’ai retourné les résultats de cette réponse dans un plug-in et je l’ai publié sur CPAN en tant que Mojolicious :: Plugin :: Renderer :: WithoutCache après avoir parlé de Grinnz sur IRC, où ils ont encouragé une sortie.

Vous pouvez l’utiliser comme ceci:

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

Il va créer un nouvel object Cache qui ne fait rien et l’installer globalement dans le moteur de rendu. De cette façon, il n’a pas besoin d’être créé à chaque fois, contrairement à la réponse initiale ci-dessous.

En théorie, cela devrait être plus rapide que l’approche de Grinnz (ce qui est plus judicieux), et puisque vous ne voulez explicitement pas mettre en cache, vous voulez évidemment que les choses soient aussi rapides que possible, n’est-ce pas? Il est censé être plus rapide parce que le véritable Mojo :: Cache devrait toujours essayer de définir le cache, mais ensuite abandonner car il n’y a plus de clés libres, et il essaierait également de rechercher les valeurs du cache à chaque fois.

Je l’ai comparé à Dumbbench et Benchmark . Les deux ont montré des résultats négligeables. Je les ai courus à quelques resockets, mais elles ont beaucoup fluctué, et on ne sait pas laquelle est la plus rapide. J’ai inclus la sortie d’une série où mon implémentation était plus rapide, mais elle montre encore à quel point la différence est minuscule.

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

Je reconnais que dans un environnement de charge lourde avec beaucoup d’appels, cela finirait par faire la différence, mais c’est très difficile à prouver. Donc, si vous n’aimez pas penser aux éléments internes du cache, ce plugin pourrait être utile.


Vieille réponse:

En regardant Mojolicious :: Plugin :: EPRenderer, j’ai découvert qu’il y avait un cache . C’est une instance de Mojo :: Cache , qui a les méthodes get , set et max_keys , et hérite de Mojo :: Base (comme probablement tout dans Mojolicious).

Le :: EPRenderer obtient un $renderer , qui est un Mojolicious :: Renderer . Il contient l’instance Mojo :: Cache. J’ai regardé $c avec Data :: Printer et j’ai découvert qu’il y avait une application $c->app qui contenait toutes ces applications.

Sachant cela, vous pouvez facilement créer votre propre classe de cache qui ne fait rien.

 package Renderer::NoCache; use Mojo::Base -base; sub get {} sub set {} sub max_keys {} 

Maintenant vous le collez dans $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 =%>. 

Maintenant, chaque tentative pour get ou set le cache ne fait tout simplement rien. Il va essayer de mettre en cache, mais il ne trouvera jamais rien.

Bien sûr, ce n’est pas génial de créer un nouvel object à chaque fois. Il serait préférable de créer cet object une fois au démarrage et de l’intégrer à la version interne permanente de l’ app . Vous avez CGI, alors ça ne changera peut-être rien.


Vous pouvez aussi simplement modifier le patch de Mojo::Cache . Cette approche plus pirate fera la même chose:

 package Foo; use Mojolicious::Lite; *Mojo::Cache::get = sub { }; get '/' => sub { my $c = shift; $c->render(template => 'foo', name => 'World'); }; app->start; 

Mais méfiezvous : nous avons juste désactivé la récupération de chaque cache de votre application qui utilise Mojo :: Cache. Ce n’est peut-être pas ce que vous voulez.