Redis
View on GitHubCache'uj wartość i unieważniaj ją
Dwa narzędzia, oba w app/Support/Cache/CacheVersion.php oraz zwykły Cache:
- Pojedynczy klucz, którego właścicielem jest jedna ścieżka zapisu (powiadomienia użytkownika):
Cache::rememberiCache::forgetw tym samym serwisie. - Zakres, na który wpływa wielu piszących (kto jest członkiem czego):
CacheVersion.
1. Cache'uj odczyt w zakresie
use App\Support\Cache\CacheVersion;
public function getAllForUser(int $userId): Collection
{
return CacheVersion::remember(
CacheVersion::MEMBERSHIP,
"user:$userId:projects",
600,
fn () => $this->projectRepository->getAllForUser($userId),
);
}
Klucz zawiera bieżącą wersję zakresu, więc bump() unieważnia wszystkie klucze zakresu naraz, a stare wpisy wygasają przez TTL. Nie ma tagów (store database ich nie wspiera) ani list kluczy do utrzymania.
2. Podnoś wersję przy każdym zapisie, który zmienia odpowiedź
CacheVersion::bump(CacheVersion::MEMBERSHIP);
Zakres członkostwa jest podnoszony z repozytoriów, które zapisują członkostwo, role i uprawnienia: ProjectMemberRepository, ProjectRepository (attachMember, update, delete), RoleRepository (delete, syncPermissions), UserRepository::delete, ProjectInvitationService (przyjęcie zaproszenia) oraz komenda GrantPermissionsToExistingRoles.
Jeśli dodajesz nowy sposób zmiany członkostwa, roli lub uprawnień roli, podnieś wersję tam. Pominięte bump oznacza nieaktualne uprawnienie przez maksymalnie TTL (10 minut), a to błąd bezpieczeństwa, nie kosmetyczny. Masowe aktualizacje przez query builder oraz attach()/sync() na pivotach nie wywołują zdarzeń modeli, dlatego bump siedzą w repozytoriach, a nie w obserwatorach.
Listy zgłoszeń
IssueService cache'uje listy jako zwykłe tablice, do których serializuje je Inertia (nigdy jako modele Eloquent: config/cache.php ustawia serializable_classes na false, więc Redis zwraca obiekty jako niekompletne klasy; dla list modeli użyj CachedModels). Zależą od trzech zakresów:
CacheVersion::ISSUESjest podnoszony przy każdym zapisie i usunięciuIssue,IssueTypelubWorkflowStatus(traitBumpsIssueCache). Aktualizacje i usunięcia przez query builder nie wywołują zdarzeń modeli, więc podnoszą go ręcznie (IssueRepository::bulkDelete, reset workflow wIssueTypeService).CacheVersion::USERSjest podnoszony, gdy zmienia się imię lub avatar użytkownika albo użytkownik zostaje usunięty (traitBumpsUserCache), bo listy osadzają osoby.CacheVersion::MEMBERSHIP(tylko dashboard), bo wypisuje każdy projekt, do którego użytkownik należy.
Jeśli dodasz zapis do zgłoszeń, typów zgłoszeń lub statusów, który omija zdarzenia modeli (Issue::query()->update(...), surowy SQL), podnieś CacheVersion::ISSUES. Jeśli lista zaczyna osadzać nowy powiązany model, nadaj mu też BumpsIssueCache.
3. Testuj w obu kierunkach
Dodaj zapis do tests/Feature/MembershipCacheInvalidationTest.php (wersja się podniosła) oraz, dla zachowania, do tests/Feature/ProjectMembershipCacheTest.php (odpowiedź zmieniła się od razu). Użyj tam queryCount(), żeby udowodnić, że powtórny odczyt nie wykonuje zapytań.
Kiedy nie cache'ować
- Czegokolwiek, co musi być dokładne teraz i nie ma jednej ścieżki zapisu.
- Wartości zmieniających się przy większości żądań (na przykład
projects.next_issue_number). - Danych tanich i rzadko czytanych.
