Clear tagged cache from Laravel Lighthouse

91 Views Asked by At

I'm trying to integrate caching in to my Laravel (9) Lighthouse (6) application and private caches seem to work correctly, but I can't seem to find a way to clear them effectively without running artisan cache:clear. Take this simplified example: Query me returns authenticated user:

extend type Query @guard {
    me: User @auth @cache(private: true)
}

Then I want to have a query or mutation which sole purpose is to clear this cache. So I created just that:

extend type Mutation @guard {
    userCacheClear(usr_id: ID!): User @update @clearCache(type: "User", idSource: {argument: "usr_id"})
}

My User type looks like this:

type User {
    usr_id: ID! @cacheKey
    usr_username: String
    usr_company: String
}

My problem is that of course userCacheClear returns correct and not cached data, but me returns still cached and at this point outdated result.

Am I missing something from the documentation? Maybe I'm doing something completely wrong?

1

There are 1 best solutions below

0
Kipras Bielinskas On

I couldn't manage to find the exact solution to my problem because for clearing all user related caches there is no common tag. So I overrode the Nuwave\Lighthouse\Cache\CacheDirective::handleField method to include an additional tag to all user private caches.

$tags = [
    $this->cacheKeyAndTags->parentTag($parentName, $rootID),
    $this->cacheKeyAndTags->fieldTag($parentName, $rootID, $fieldName)
];

// If cache is private then adding private tag for easier clearing
if($isPrivate) $tags[] = 'auth_' . $context->user()->getAuthIdentifier();

$cache = $shouldUseTags
    ? $this->cacheRepository->tags($tags)
    : $this->cacheRepository;

From the code you can see that I check if cache should be private and then add a tag auth_{user_id}.

Then registering this change in the AppServiceProvider.php

public function register(): void {
    $this->app->bind(CacheDirective::class, CacheDirectiveAdapter::class);
}

Now I'm free to run this one-liner to clear all GQL private cache for any specific user.

Cache::tags(['auth_{user_id}'])->flush()