# Livewire Cache Strategy (No Queues Required)

_Last updated: 2025-11-15_

To keep SEO-friendly SSR while avoiding slow third-party requests, Livewire pages now use `DataTransformationService::cacheComposite()` to wrap each expensive data block.

## Helper Usage

```
DataTransformationService::cacheComposite(
    $cacheKey,                 // e.g. "home_latest_en"
    $updateMinutes,            // TTL before attempting refresh
    function () {              // Producer closure that fetches data
        return $expensiveData; // Arrays or objects are fine
    },
    [],                        // Optional validation path; [] allows empty arrays
    $forceRefresh              // bool, pass request()->boolean('refresh')
);
```

Behind the scenes, `Cache::ifValid` stores `{updateDate, freshData}` forever and only refreshes once per TTL. If fetching fails, cached data is reused.

## Forcing a Refresh

Append `?refresh=1` to any of the Livewire routes (`/latest`, `/popular`, `/tag/...`, `/home`) to bypass the cached snapshot once. The request clears the cache key and repopulates it synchronously, so use sparingly.

## Current Keys & TTLs

| Page/Section        | Cache Key Pattern             | TTL (minutes)                        |
|---------------------|-------------------------------|--------------------------------------|
| Home – Latest       | `home_latest_{lang}`          | `drama.cache.latest_update_minutes`  |
| Home – Popular/Mix  | `home_popular_{lang}`         | `drama.cache.popular_update_minutes` |
| Latest listing      | `latest_{lang}_page_{n}`      | `drama.cache.list_update_minutes`    |
| Popular listing     | `popular_{lang}_page_{n}`     | `drama.cache.popular_update_minutes` |
| Tag listing         | `tag_{lang}_{slug}`           | `drama.cache.list_update_minutes`    |

Continue-watching remains user-specific and is not cached globally.
