Catalyst 模型缓存 dbix 调用

Catalyst Model cache dbix calls

我正在写一个 Catalyst application and I have a Model that represents a small settings table whose values won't change. Rather than querying the database for this every time, I would like to cache the responses. Within the model I am using DBIx::Class, and I did see this DBIx::Class::Cursor::Cached,它看起来像一个选项。

然而,我最终做的是使用 Memoize 在我的模型中缓存 return 值。我对这个解决方案有两个问题:

  1. Catalyst 模型是否只创建一次,然后在应用程序的整个生命周期内使用?还是 $c->model() 每次都创建一个新模型 class?

  2. 如果我 运行 我的应用程序有 fastcgi 并且有 6 个线程,这意味着我的应用程序的每个线程都会有自己的模型 class 并且会有进行查询并拥有 6 个独立的缓存,对吗?

这是一个糟糕的解决方案吗?我应该做点别的吗?

Are Catalyst Models only created once, and then used for the lifetime of the application? Or does $c->model() create a new Model class each time?

这取决于您对模型的实施。如果在 Initialization 下有一个 ACCEPT_CONTEXT method in your model, Catalyst will make a new object every time you call $c->model(). If not, it will be instantiated once during startup of the application. That's documented in Catalyst::Manual::Internals

YAPC::EU 2016 in Cluj the current maintainer of Catalyst, John Napiorkowski, gave a (remote) talk about Catalyst that explains this very aspect starting from about 53 minutes into the talk。整个事情以及他在那里的其他谈话都值得一看。

If I'm running my application with fastcgi and there are 6 threads, this means that each thread of my app will get its own model class and will have to make queries and hapve 6 separate caches, correct?

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


使用 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 非常适合构建事物的缓存,尽管在这里可能有点矫枉过正。