Catalyst Model缓存dbix调用

时间:2016-10-04 08:07:59

标签: perl caching catalyst dbix-class

我正在撰写Catalyst应用程序,我有Model代表一个小的设置表,其值不会发生变化。我不是每次都要查询数据库,而是要缓存响应。在我使用DBIx::Class的模型中,我确实看到了DBIx::Class::Cursor::Cached,这看起来像一个选项。

但是,我最终做的是使用Memoize来缓存模型中的返回值。关于这个解决方案我有两个问题:

  1. Catalyst模型是否只创建一次,然后用于应用​​程序的生命周期?或者$c->model()每次都创建一个新的Model类?

  2. 如果我使用fastcgi运行我的应用程序并且有6个线程,这意味着我的应用程序的每个线程都将获得自己的模型类,并且必须进行查询并且需要6个单独的缓存,正确?

  3. 这是一个糟糕的解决方案吗?我应该做些什么吗?

1 个答案:

答案 0 :(得分:2)

  

Catalyst模型是否只创建一次,然后用于应用​​程序的生命周期?或者$c->model()每次都创建一个新的Model类吗?

这取决于您对模型的实施。如果模型中有ACCEPT_CONTEXT方法,则每次调用$c->model()时,Catalyst都会生成一个新对象。如果没有,它将在应用程序启动期间实例化一次。这在初始化下的Catalyst::Manual::Internals中有记录。

YAPC::EU 2016 in Cluj,Catalyst的当前维护者John Napiorkowski发表了关于Catalyst的(远程)谈话,解释了从from about 53 minutes into the talk开始的这个方面。整个事情以及他的其他演讲值得关注。

  

如果我使用fastcgi运行我的应用程序并且有6个线程,这意味着我的应用程序的每个线程都将获得自己的模型类,并且必须进行查询并且需要6个单独的缓存,对吗?

我不确定那个。我相信它会启动一次,然后分叉。所以它会创建一个实例并将其复制到fork。

使用DBIx :: Class :: Cursor :: Cached为您的方法看起来会起作用。如果你需要DBIx :: Class ResultSet对象,那很好。如果没有,您可以将结果作为惰性属性附加到模型中。它可能看起来像这样:

package My::Model;
use Mooose;
use My::DB::Schema;
extends 'Catalyst::Model';

has stuff => (
    is => 'ro',
    isa => 'HashRef',
    traits => ['Hash'],
    handles => {
        has_stuff => 'exists',
        get_stuff => 'get',
        # ...
    },
    lazy => 1,
    builder => '_build_stuff',
);

sub _build_stuff {
    my ($self) = @_;

    # get stuff from the DB here, convert it to a config hash
    # or whatever you need and store it in our stuff attribute

    # that works well if your config looks something like this:

    # {
    #     color => 'red',
    #     price => 13.37,
    #     things => [ qw/ foo bar baz / ],
    #     # ...
    # }

    # you can then use the Hash trait on your attribute to access it
}

1;

这样它会在你第一次使用它时加载它,然后你就完成了。它只会存储在对象中。

如果您想调查实际上是否有效并且不执行更多查询,可以使用DBIC_TRACE=1环境变量启用DBIC 's tracing output。它会将彩色查询转储到您的Catalyst日志中。

或者,CHI非常适合构建缓存的东西,虽然这里可能有点矫枉过正。