Skip to content

Instantly share code, notes, and snippets.

@Gummibeer
Created February 6, 2024 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gummibeer/6e018265663e73780d633c35c7829dd4 to your computer and use it in GitHub Desktop.
Save Gummibeer/6e018265663e73780d633c35c7829dd4 to your computer and use it in GitHub Desktop.
<?php
Repository::macro('swr', function (string $key, DateInterval|DateTimeInterface|int $tts, DateInterval|DateTimeInterface|int $ttl, Closure $callback): mixed {
/** @var Repository $this */
if ($this->getSeconds($tts) >= $this->getSeconds($ttl)) {
throw new UnexpectedValueException('The time-to-stale value must be less than the time-to-live value.');
}
$ttsKey = "{$key}:tts";
$revalidatingKey = "{$key}:revalidating";
// Re-implement the logic of the `remember()` method to avoid the overhead of
// calling `has()` twice on the same key, as well as the need to `forget()`
// the key before the value is ready to be set in cache.
$remember = fn () => tap($callback(), function (mixed $value) use ($key, $ttl, $ttsKey, $tts) {
/** @var Repository $this */
$this->put($key, $value, value($ttl, $value));
$this->put($ttsKey, true, value($tts, true));
});
// Set the value in cache if key doesn't exist.
if ($this->missing($key)) {
return $remember();
}
app()->terminating(function () use ($ttsKey, $revalidatingKey, $remember) {
/** @var Repository $this */
if ($this->has($ttsKey) || $this->has($revalidatingKey)) {
return;
}
$this->put($revalidatingKey, true);
rescue($remember);
});
return $this->get($key);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment