Najlepsze praktyki wdrażania niestandardowego buforowania?

17

Dla każdej instancji każdego typu encji generuję szereg pamięci podręcznych o nazwach takich jak: [module_name]__[entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from]

Teraz za każdym razem, gdy jednostka jest aktualizowana, chcę porzucić wszystkie pamięci podręczne, zaczynając od odpowiedniego typu jednostki i identyfikatora.

Jak przechowywać / wyczyścić te pamięci podręczne?

Obecnie po prostu cache_set () , ale stanowi to problem, gdy chcę wyczyścić, ponieważ nie znam nazw wszystkich odpowiednich pamięci podręcznych. Czy bezpieczne jest upuszczanie wpisów w pamięci podręcznej za pomocą funkcji db_delete ()?

Letharion
źródło
Jeśli nie znasz nazw wszystkich odpowiednich pamięci podręcznych, jak możesz tego użyć db_delete()?
kiamlaluno

Odpowiedzi:

6

Aby usunąć wpisy z pamięci podręcznej, należy użyć cache_clear_all () . Powodem jest to, że używana implementacja pamięci podręcznej nie mogła użyć tabeli bazy danych w aktywnej bazie danych. Tak dzieje się z klasą DrupalDatabaseCache , ale nie powinno tak być w przypadku wszystkich klas.

Jeśli spojrzysz na _cache_get_object () (funkcję wywoływaną przez cache_get () i cache_set () ), zauważysz, że zawiera następujący kod.

  static $cache_objects; 
  if (!isset($cache_objects[$bin])) {
    $class = variable_get('cache_class_' . $bin);
    if (!isset($class)) {
      $class = variable_get('cache_default_class', 'DrupalDatabaseCache');
    }
    $cache_objects[$bin] = new $class($bin);
  }
  return $cache_objects[$bin];

Klasa implementacji pamięci podręcznej może być inna dla każdego magazynu bin pamięci podręcznej, a nawet domyślną można zmienić.

System pamięci podręcznej statusu aktualizacji prywatnej dokładnie wyjaśnia, dlaczego normalne funkcje pamięci podręcznej nie są używane w _update_cache_clear () , _update_cache_get () i _update_cache_set () . (Nacisk jest mój.)

W szczególności NIE używamy interfejsu API podstawowej pamięci podręcznej do zapisywania pobranych danych o dostępnych aktualizacjach. Bardzo ważne jest, aby pamięć podręczna została wyczyszczona tylko wtedy, gdy zapełniamy ją po pomyślnym pobraniu nowych dostępnych danych aktualizacji. Korzystanie z interfejsu API podstawowej pamięci podręcznej powoduje różnego rodzaju potencjalne problemy, które mogłyby spowodować ciągłą próbę pobrania dostępnych danych aktualizacji, w tym jeśli witryna ma zdefiniowany „minimalny czas życia bufora” (który jest zarówno minimalny, jak i maksymalny), lub jeśli witryna korzysta z memcache lub innego podłączanego systemu pamięci podręcznej, który przyjmuje zmienne pamięci podręczne.

Moduł Menedżera aktualizacji nadal korzysta z tabeli {cache_update}, ale zamiast używać cache_set(), cache_get()i cache_clear_all()istnieją prywatne funkcje pomocnicze, które implementują te same podstawowe zadania, ale zapewniają, że pamięć podręczna nie zostanie przedwcześnie wyczyszczona, a dane są zawsze przechowywane w baza danych, nawet jeśli używana jest pamięć podręczna lub inny backend pamięci podręcznej.

Menedżer aktualizacji ma określone potrzeby, które są konieczne, ponieważ zbyt częste pobieranie informacji o aktualizacji spowodowałoby problemy z serwerami Drupal.org, biorąc pod uwagę, że Menedżer aktualizacji może potencjalnie pobierać informacje o aktualizacji z dowolnej witryny z uruchomionym Drupal.

W twoim przypadku możesz użyć [module_name]__[entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from]jako identyfikatora pamięci podręcznej dla jednego magazynu bin pamięci podręcznej. W przypadku, gdy musisz usunąć wszystkie wpisy dla encji, możesz użyć następującego kodu.

cache_clear_all("{$module}__{$entity_type}__{$entity_id}__", $bin, TRUE);

Jeśli nie możesz uzyskać wartości do przypisania $modulepodczas czyszczenia pamięci podręcznej lub chcesz usunąć pozycję pamięci podręcznej niezależnie od modułu, dla którego dane zostały buforowane, możesz użyć innego identyfikatora pamięci podręcznej, takiego jak [entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from]lub [entity_type]__[entity_id]__[module_name]__[string_depending_on_where_the_cache_came_from]. cache_clear_all()usuwa wszystkie wpisy pamięci podręcznej o identyfikatorze pamięci podręcznej rozpoczynającym się od łańcucha przekazanego jako argument, gdy $wildcardjest TRUE, a identyfikator pamięci podręcznej nie jest '*'. W takim przypadku pamięć podręczna zostanie wyczyszczona za pomocą następującego kodu.

cache_clear_all("{$entity_type}__{$entity_id}__", $bin, TRUE);
kiamlaluno
źródło
8

Nie mogę wymyślić dobrego powodu, dla którego ręczne usunięcie wpisów spowodowałoby problem. Zakłada się oczywiście, że używasz MySQL jako backendu dla twojej konkretnej pamięci podręcznej; chociaż myślę, że to samo dotyczy każdego innego rodzaju zaplecza pamięci podręcznej, metoda czyszczenia po prostu niekoniecznie byłaby zapytaniem do bazy danych.

Jeśli weźmiesz przykładowy moduł aktualizacji rdzenia, pomija on cache_*funkcje i ręcznie czyści pamięć podręczną:

function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
  if (empty($cid)) {
    db_delete('cache_update')
      // Clear everything except fetch task information because these are used
      // to ensure that the fetch task queue items are not added multiple times.
      ->condition('cid', 'fetch_task::%', 'NOT LIKE')
      ->execute();
  }
  else {
    $query = db_delete('cache_update');
    if ($wildcard) {
      $query->condition('cid', $cid . '%', 'LIKE');
    }
    else {
      $query->condition('cid', $cid);
    }
    $query->execute();
  }
}

Zawsze myślę: „jeśli jest wystarczająco dobry dla rdzenia, jest dla mnie wystarczająco dobry” :)

Clive
źródło