Perl Catalyst DBIx Cursor Cache - как очистить? - PullRequest
0 голосов
/ 09 февраля 2012

приносит свои извинения и заранее благодарит за то, что, даже когда я печатаю, кажется, вероятно, глупый вопрос, но здесь все равно.

У меня есть базовое Catalyst приложение, использующее DBIx ::Класс с таблицей «Автор» и связанной таблицей «Книга».Кроме того, я также использую DBIx :: Class :: Cursor :: Cached , чтобы кэшировать данные соответствующим образом.

Проблема в том, что после редактирования мне нужно очистить кэшированные данные ДО того, как они действительно истекут.
1.) Author-> show_author_and_books , которая выбирает и кэширует набор результатов.

2.) Book-> edit_do , который должен очистить кэшированные данные из запроса Author-> show_author_and_books .

См. Базовый / соответствующийнастройки ниже.

- определение MyApp.pm, включая внутренний кеш 'Cache :: FileCache'.

__PACKAGE__->config(
name         => 'MyApp',
...

'Plugin::Cache' => {   'backend' => { class              => 'Cache::FileCache',
                                      cache_root         => "./cache",
                                      namespace          => "dbix",
                                      default_expires_in => '8 hours',
                                      auto_remove_stale  => 1
                                    }
                   },
...

- определение MyApp :: Model :: DB с установленными признаками 'Caching'используя 'DBIx :: Class :: Cursor :: Cached'.

...
__PACKAGE__->config(
schema_class => 'MyApp::Schema',

traits       => [ 'Caching' ],

connect_info => { dsn          => '<dsn>',
                  user         => '<user>',
                  password     => '<password>',
                  cursor_class => 'DBIx::Class::Cursor::Cached'
                }
);
...

- определение MyApp :: Controller :: Author.pm с методом 'show_author_and_books' - набор результатов кэшируется.

...
sub show_author_and_books :Chained('base') :PathPart('') :Args(0)
{
    my ( $self, $c ) = @_;

    my $author_id = $c->request->params->{author_id};

    my $author_and_books_rs = $c->stash->{'DB::Author'}->search({ author_id => $author_id },
                                                            { prefetch  =>  'book' },
                                                              cache_for =>  600 } ); # Cache results for 10 minutes.

    # More interesting stuff, but no point calling $author_and_books_rs->clear_cache here, it would make no sense:s
    ...

}

...    

- Определение MyApp :: Controller :: Book.pm с помощью метода * edit_do , который обновляет запись в книге и, таким образом, делает недействительными кэшированные данные в show_author_and_books .

...
sub edit_do :Chained('base') :PathPart('') :Args(0)
{
    my ( $self, $c ) = @_;

    # Assume stash contains a book for some author, and that we want to update the description.

    my $book = $c->stash->{'book'}->update({ desc => $c->request->params->{desc} });

    # How do I now clear the cached DB::Author data to ensure the new desc is displayed on next request to 'Author->show_author_and_books'?

    # HOW DO I CLEAR CACHED DB::Author DATA?

    ...
} 

Естественно, я знаю, что $ author_and_books_rs , как определено в Author-> show_author_and_books , содержит метод ' clear_cache ', но, очевидно, это выходит за рамки Book-> edit_do (не говоря уже о другой возможной проблеме).

Итак, правильный ли способ сделать запрос DBIx снова, согласно ... show_author_and_books , а затем снова вызвать 'clear_cache', или есть более прямой способ, где я могу просто что-то сказатьвот так $ c-> cache -> ('DB :: Author') -> clear_cache?

Еще раз спасибо.

PS.Я уверен, когда я посмотрю на это завтра, полная глупость вопроса поразит меня: s

Ответы [ 3 ]

0 голосов
/ 14 февраля 2012

В итоге я решил НЕ использовать DBIx :: Class :: Cursor :: Cached, а вместо этого напрямую использовать плагин Catalyst Cache, определяющий несколько внутренних кэшей для обработки различных пространств имен, которыми я пытаюсь управлятьсценарий реального мира.

Я отступил от D :: C :: Cursor :: Cached, так как все данные были / хранятся в одном и том же пространстве имен, плюс, похоже, не существует метода для истечения срока действия данных ранее установленного времени.

Таким образом, для полноты из вышеприведенного кода определение MyApp :: Model :: DB.pm потеряло бы ключ / значения 'traits' и 'cursor_class'.

Тогда ...

Расширение MyApp.pm Plugin :: Cache 'будет содержать несколько пространств имен кэша ...

-- MyApp.pm definition including backend 'Cache::FileCache' cache.

... 
'Plugin::Cache' => { 'backends' => { Authors => { class              => 'Cache::FileCache',
                                                  cache_root         => "./cache",
                                                  namespace          => "Authors",
                                                  default_expires_in => '8 hours',
                                                  auto_remove_stale  => 1
                                                },
                                     CDs  => { class                     => 'Cache::FileCache',
                                                      cache_root         => "./cache",
                                                      namespace          => "CDs",
                                                      default_expires_in => '8 hours',
                                                      auto_remove_stale  => 1
                                                },
                                    ...            
                                   }
...                                   

- определение MyApp :: Controller :: Author.pm с указанием' show_author_and_books'method - resultset кэшируется.

...
sub show_author_and_books :Chained('base') :PathPart('') :Args(0)
{
    my ( $self, $c ) = @_;

    my $author_id = $c->request->params->{author_id};

    my $author = $c->get_cache_backend('Authors')->get( $author_id );

    if( !defined($author) )
    {
        $author = $c->stash->{'DB::Author'}->search({ author_id => $author_id },
                                                    { prefetch  =>  'book', rows => 1 } )->single;

        $c->get_cache_backend('Authors')->set( $author_id, $author, "10 minutes" );
    }                                                              

    # More interesting stuff, ...
    ...
}

... 

- определение MyApp :: Controller :: Book.pm с методом edit_do, который обновляет запись в книге и, таким образом, делает недействительными кэшированные данные в show_author_and_books.

...
sub edit_do :Chained('base') :PathPart('') :Args(0)
{
    my ( $self, $c ) = @_;

    # Assume stash contains a book for some author, and that we want to update the description.

    my $book = $c->stash->{'book'}->update({ desc => $c->request->params->{desc} });

    # How do I now clear the cached DB::Author data to ensure the new desc is displayed on next request to 'Author->show_author_and_books'?

    # HOW DO I CLEAR CACHED DB::Author DATA? THIS IS HOW, EITHER...

    $c->get_cache_backend('Authors')->set( $c->stash->{'book'}->author_id, {}, "now" ); # Expire now.

    # ... OR ... THE WHOLE Authors namespace...

    $c->get_cache_backend('Authors')->clear;    

    ...
}

ПРИМЕЧАНИЕ: как вы и ожидаете от использования Author и CD, я работаю не по сценарию реального мира, а должен показать мои намерения.

Как яЯ относительно новичок в чуде DBIx и, действительно, Catalyst, мне было бы интересно услышать, еслиЕсть лучший подход к этому (я очень ожидаю, что есть), но он будет служить на данный момент, когда я пытаюсь обновить устаревшее приложение.

0 голосов
/ 04 августа 2014

Плагин, вероятно, можно было бы пропатчить, чтобы сделать кэши для каждого набора результатов легко доступными для пространства имен и очищаться независимо, а в качестве альтернативы было бы не так сложно добавить пространство имен к атрибутам. Если вы хотите поработать над этим хитом # dbix-class, и я был бы готов наставить вас - jnap

0 голосов
/ 09 февраля 2012

Попробуйте

$c->model( 'DB::Author' )->clear_cache() ;
...