diff --git a/.env.example b/.env.example index 22a153437..f5f4aad61 100644 --- a/.env.example +++ b/.env.example @@ -89,3 +89,6 @@ WEBHOOK_TIMEOUT=10 WEBHOOK_INFO=false FLAG_VALIDATE_ADDRESS_FULLNAME=true + +MEDIA_CACHE_CORE_ID=core_id +MEDIA_CACHE_TTL=86400 diff --git a/app/Console/Commands/MediaCache.php b/app/Console/Commands/MediaCache.php new file mode 100644 index 000000000..451099b92 --- /dev/null +++ b/app/Console/Commands/MediaCache.php @@ -0,0 +1,36 @@ +cursor() as $media) { + $mediaService->addMediaToCache($media); + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 7663b65b2..c351ce000 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,6 +2,7 @@ namespace App\Console; +use App\Console\Commands\MediaCache; use App\Jobs\CheckActiveSales; use App\Jobs\GoogleCategoryJob; use App\Jobs\StopShippingUnlimitedStockDateJob; @@ -33,5 +34,7 @@ protected function schedule(Schedule $schedule): void $schedule->job(new GoogleCategoryJob()) ->weekly() ->sentryMonitor('google-category'); + + $schedule->command(MediaCache::class)->dailyAt('01:00'); } } diff --git a/app/Http/Resources/MediaCacheResource.php b/app/Http/Resources/MediaCacheResource.php new file mode 100644 index 000000000..efed2ea02 --- /dev/null +++ b/app/Http/Resources/MediaCacheResource.php @@ -0,0 +1,24 @@ + $this->resource->getKey(), + 'type' => $this->resource->type->value, + 'source' => $this->resource->source->value, + 'url' => $this->resource->url, + 'slug' => $this->resource->slug, + 'alt' => $this->resource->alt, + ]; + } +} diff --git a/app/Services/Contracts/MediaServiceContract.php b/app/Services/Contracts/MediaServiceContract.php index ca4a97682..2df4e7565 100644 --- a/app/Services/Contracts/MediaServiceContract.php +++ b/app/Services/Contracts/MediaServiceContract.php @@ -17,4 +17,6 @@ public function store(MediaDto $dto, bool $private = false): Media; public function update(Media $media, MediaDto $dto): Media; public function destroy(Media $media): void; + + public function addMediaToCache(Media $media): void; } diff --git a/app/Services/MediaService.php b/app/Services/MediaService.php index d7e083b10..f58877846 100644 --- a/app/Services/MediaService.php +++ b/app/Services/MediaService.php @@ -5,6 +5,7 @@ use App\Dtos\MediaDto; use App\Enums\MediaSource; use App\Enums\MediaType; +use App\Http\Resources\MediaCacheResource; use App\Models\Media; use App\Models\Product; use App\Services\Contracts\MediaServiceContract; @@ -13,6 +14,8 @@ use App\Services\Contracts\SilverboxServiceContract; use Heseya\Dto\Missing; use Illuminate\Http\UploadedFile; +use Illuminate\Support\Facades\Config; +use Illuminate\Support\Facades\Redis; final readonly class MediaService implements MediaServiceContract { @@ -49,6 +52,7 @@ public function syncRewards(Product $product, array $media): void public function destroy(Media $media): void { $this->silverboxService->delete($media->url); + $this->removeMediaFromCache($media); $media->forceDelete(); } @@ -89,6 +93,8 @@ public function store(MediaDto $dto, bool $private = false): Media $this->metadataService->sync($media, $dto->getMetadata()); } + $this->addMediaToCache($media); + return $media; } @@ -108,6 +114,8 @@ public function update(Media $media, MediaDto $dto): Media $media->save(); + $this->addMediaToCache($media); + return $media; } @@ -120,4 +128,20 @@ private function getMediaType(string $extension): MediaType default => MediaType::OTHER, }; } + + public function addMediaToCache(Media $media): void + { + $redis = Redis::connection('noprefix'); + $key = 'm_' . Config::get('cache.media_cache_core_id') . '_' . $media->getKey(); + + $redis->del($key); + $redis->hmset($key, ['d' => json_encode(MediaCacheResource::make($media)->resolve())]); + $redis->expire($key, Config::get('cache.media_cache_ttl')); + } + + public function removeMediaFromCache(Media $media): void + { + $key = 'm_' . Config::get('cache.media_cache_core_id') . '_' . $media->getKey(); + Redis::connection('noprefix')->del($key); + } } diff --git a/config/cache.php b/config/cache.php index a1aac8835..60e5b0f39 100644 --- a/config/cache.php +++ b/config/cache.php @@ -95,4 +95,7 @@ */ 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'heseya_store'), '_') . '_cache'), + + 'media_cache_core_id' => env('MEDIA_CACHE_CORE_ID', 'core_id'), + 'media_cache_ttl' => env('MEDIA_CACHE_TTL', 3600), ]; diff --git a/config/database.php b/config/database.php index 8f974a836..9da4b86a1 100644 --- a/config/database.php +++ b/config/database.php @@ -120,5 +120,16 @@ 'scheme' => env('REDIS_CACHE_SCHEME', 'tcp'), 'path' => env('REDIS_CACHE_PATH', ''), ], + + 'noprefix' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'password' => env('REDIS_PASSWORD', null), + 'port' => env('REDIS_PORT', 6379), + 'database' => env('REDIS_DB', 0), + 'scheme' => env('REDIS_SCHEME', 'tcp'), + 'path' => env('REDIS_PATH', ''), + 'prefix' => '', + ] ], ];