Cache::flexible does not refresh in the background between stale period #58189
Replies: 9 comments
-
|
during the stale window Cache::flexible should return the stale value immediately and trigger a refresh in the background (only one process obtains the refresh lock). If you see the value only change after full expiry, common causes are the cache driver not supporting atomic locks or the refresh being dispatched to the queue with no worker running. file and array drivers don't support atomic locks. Check only one request can refresh. If lock acquisition fails or the callback throws, no refresh will happen. this logs when the flexible callback actually runs so you can see whether refresh runs during the stale window. Route::get('/test-flexible', function () {
$now = Cache::flexible('dateeeeee17', [10, 60], function () {
\Log::info('flexible callback ran', ['time' => now()->toTimeString()]);
return now()->toTimeString();
});
return view('test', compact('now'));
}); |
Beta Was this translation helpful? Give feedback.
-
|
@miladev95 |
Beta Was this translation helpful? Give feedback.
-
|
A few quick checks:
If you still don’t see the log entry during the stale period, the refresh job is not being dispatched. If you see an exception in the logs, paste the trace here and I’ll help diagnose it. |
Beta Was this translation helpful? Give feedback.
-
|
@miladev95 Is a queue actually used for updating the cache in this case? |
Beta Was this translation helpful? Give feedback.
-
|
Yes, a log inside the <?php
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Event;
use Illuminate\Queue\Events\JobProcessing;
use Illuminate\Queue\Events\JobFailed;
// 1) Log inside the flexible callback to confirm background execution
$now = Cache::flexible('dateeeeee17', [10, 60], function () {
$val = \Carbon\Carbon::now()->toTimeString();
Log::info('flexible refresh executed', ['time' => $val, 'context' => 'background_refresh']);
return $val;
});
// 2) Add these listeners in `app/Providers/AppServiceProvider.php` -> boot()
// to see queued jobs being processed or failing
Event::listen(JobProcessing::class, function (JobProcessing $event) {
Log::info('job processing', [
'name' => method_exists($event->job, 'resolveName') ? $event->job->resolveName() : get_class($event->job),
'id' => method_exists($event->job, 'getJobId') ? $event->job->getJobId() : null,
]);
});
Event::listen(JobFailed::class, function (JobFailed $event) {
Log::error('job failed', [
'name' => method_exists($event->job, 'resolveName') ? $event->job->resolveName() : get_class($event->job),
'exception' => $event->exception->getMessage(),
]);
});If these produce no log lines during the stale window, the refresh job is not being queued, re-check |
Beta Was this translation helpful? Give feedback.
-
|
@miladev95 |
Beta Was this translation helpful? Give feedback.
-
|
Moved this to discussion as the problem didn't occur in a fresh installation. I believe this is something specific the the application. |
Beta Was this translation helpful? Give feedback.
-
|
I was experiencing the exact same issue after upgrading an older Laravel project to Laravel 12. In my case, adding the following middleware fixed it. In After this change, the problem was resolved. |
Beta Was this translation helpful? Give feedback.
-
|
The root cause is that the
For Fix for apps with protected $middlewareGroups = [
'web' => [
\Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks::class,
// ... rest of your middleware
],
];Fix for apps using ->withMiddleware(function (Middleware $middleware) {
$middleware->web(prepend: [
\Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks::class,
]);
})Once the middleware is present, the stale-period background refresh should work as expected. No queue worker or Horizon configuration should be needed |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Laravel Version
12
PHP Version
8.3
Database Driver & Version
No response
Description
Hi. I am using the Cache::flexible method as follows:
$now = Cache::flexible('dateeeeee17', [10, 60], function () { return Carbon::now()->toTimeString(); }); return view('test', compact('now'));Here is the behavior I am observing:
On the initial request, I get 12:00:00.
For the first 10 seconds (the "fresh" period), the cache correctly returns the same value.
Between 10 and 60 seconds (the "stale" period), I refresh the page several times at 5-second intervals. According to the documentation, the cache should refresh in the background during this period.
However, I still keep seeing the initial value (12:00:00). The new value only appears after 60 seconds, when the cache expires.
It seems that no background refresh is happening during the stale period, contrary to what the documentation suggests.
I have tried searching for existing issues or discussions but couldn’t find anything. Any guidance or confirmation on whether this is expected behavior would be appreciated.
Thank you!
Steps To Reproduce
no steps
Beta Was this translation helpful? Give feedback.
All reactions