From 0d62fba1c268efa0a7d8c2d92bed50423ab6420c Mon Sep 17 00:00:00 2001 From: Manus AI Date: Wed, 11 Feb 2026 03:40:04 -0500 Subject: [PATCH] feat: Include updated_at timestamp in UserCacheService cache key This enhancement adds the user's updated_at timestamp to the cache key generation in UserCacheService, enabling automatic cache busting when user data is modified. Changes: - Updated getCacheKey() to accept User object and include updated_at timestamp - Modified get(), put(), and invalidate() methods to work with User objects - Updated UserController to pass User object to cache methods - Added clarifying comments in UserObserver and User model Benefits: - Automatic cache invalidation when user data changes - Improved cache consistency and data freshness - Aligns with existing ETag implementation - Simplifies cache management logic --- .../Internal/v1/UserController.php | 4 +- src/Models/User.php | 2 + src/Observers/UserObserver.php | 2 + src/Services/UserCacheService.php | 51 +++++++++++-------- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/Http/Controllers/Internal/v1/UserController.php b/src/Http/Controllers/Internal/v1/UserController.php index 02e1677..12e86b0 100644 --- a/src/Http/Controllers/Internal/v1/UserController.php +++ b/src/Http/Controllers/Internal/v1/UserController.php @@ -182,7 +182,7 @@ public function current(Request $request) // Try to get from server cache $companyId = session('company'); - $cachedData = UserCacheService::get($user->id, $companyId); + $cachedData = UserCacheService::get($user, $companyId); if ($cachedData) { // Return cached data with cache headers @@ -202,7 +202,7 @@ public function current(Request $request) $userArray = $userData->toArray($request); // Store in cache - UserCacheService::put($user->id, $companyId, $userArray); + UserCacheService::put($user, $companyId, $userArray); // Return with cache headers return response()->json(['user' => $userArray]) diff --git a/src/Models/User.php b/src/Models/User.php index 7cc1ab6..881c734 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -1343,6 +1343,8 @@ public function assignSingleRole($role): self $this->companyUser->assignSingleRole($role); // Invalidate user cache after role change + // Note: With updated_at in cache key, this provides immediate invalidation + // while the timestamp-based key provides automatic cache busting \Fleetbase\Services\UserCacheService::invalidateUser($this); return $this; diff --git a/src/Observers/UserObserver.php b/src/Observers/UserObserver.php index 820c994..ca72645 100644 --- a/src/Observers/UserObserver.php +++ b/src/Observers/UserObserver.php @@ -15,6 +15,8 @@ class UserObserver public function updated(User $user): void { // Invalidate user cache when user is updated + // Note: With updated_at in cache key, this provides immediate invalidation + // while the timestamp-based key provides automatic cache busting UserCacheService::invalidateUser($user); // Invalidate organizations cache (user might be an owner) diff --git a/src/Services/UserCacheService.php b/src/Services/UserCacheService.php index f2d9a56..db3b678 100644 --- a/src/Services/UserCacheService.php +++ b/src/Services/UserCacheService.php @@ -25,29 +25,34 @@ class UserCacheService /** * Generate cache key for a user and company. + * Includes the user's updated_at timestamp for automatic cache busting. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @return string */ - public static function getCacheKey($userId, string $companyId): string + public static function getCacheKey(User $user, string $companyId): string { - return self::CACHE_PREFIX . $userId . ':' . $companyId; + return self::CACHE_PREFIX . $user->uuid . ':' . $companyId . ':' . $user->updated_at->timestamp; } /** * Get cached user data. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @return array|null */ - public static function get($userId, string $companyId): ?array + public static function get(User $user, string $companyId): ?array { - $cacheKey = self::getCacheKey($userId, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); try { $cached = Cache::get($cacheKey); if ($cached) { Log::debug('User cache hit', [ - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, 'cache_key' => $cacheKey, ]); @@ -57,7 +62,7 @@ public static function get($userId, string $companyId): ?array } catch (\Exception $e) { Log::error('Failed to get user cache', [ 'error' => $e->getMessage(), - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, ]); @@ -68,18 +73,22 @@ public static function get($userId, string $companyId): ?array /** * Store user data in cache. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @param array $data + * @param int|null $ttl + * @return bool */ - public static function put($userId, string $companyId, array $data, ?int $ttl = null): bool + public static function put(User $user, string $companyId, array $data, ?int $ttl = null): bool { - $cacheKey = self::getCacheKey($userId, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); $ttl = $ttl ?? self::CACHE_TTL; try { Cache::put($cacheKey, $data, $ttl); Log::debug('User cache stored', [ - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, 'cache_key' => $cacheKey, 'ttl' => $ttl, @@ -89,7 +98,7 @@ public static function put($userId, string $companyId, array $data, ?int $ttl = } catch (\Exception $e) { Log::error('Failed to store user cache', [ 'error' => $e->getMessage(), - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, ]); @@ -108,7 +117,7 @@ public static function invalidateUser(User $user): void // Clear cache for each company foreach ($companies as $companyId) { - $cacheKey = self::getCacheKey($user->id, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); Cache::forget($cacheKey); Log::debug('User cache invalidated', [ @@ -121,7 +130,7 @@ public static function invalidateUser(User $user): void // Also clear for current session company if different $sessionCompany = session('company'); if ($sessionCompany && !in_array($sessionCompany, $companies)) { - $cacheKey = self::getCacheKey($user->id, $sessionCompany); + $cacheKey = self::getCacheKey($user, $sessionCompany); Cache::forget($cacheKey); Log::debug('User cache invalidated for session company', [ @@ -141,24 +150,26 @@ public static function invalidateUser(User $user): void /** * Invalidate cache for a specific user and company. * - * @param int|string $userId + * @param User $user + * @param string $companyId + * @return void */ - public static function invalidate($userId, string $companyId): void + public static function invalidate(User $user, string $companyId): void { - $cacheKey = self::getCacheKey($userId, $companyId); + $cacheKey = self::getCacheKey($user, $companyId); try { Cache::forget($cacheKey); Log::debug('User cache invalidated', [ - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, 'cache_key' => $cacheKey, ]); } catch (\Exception $e) { Log::error('Failed to invalidate user cache', [ 'error' => $e->getMessage(), - 'user_id' => $userId, + 'user_id' => $user->uuid, 'company_id' => $companyId, ]); }