Replies: 3 comments 5 replies
-
Since there might be many people relying on the current behaviour, I'm going to leave things as they are for now. |
Beta Was this translation helpful? Give feedback.
-
came across similar myself today. Perhaps it's a good idea to note this in the documentation? or add a flag/extra function? although with once coming natively to Laravel 11, this might be a change you want also to be adopted there. As a workaround, people can add the following to a Function helper file in their projects. The body is the same as the use Spatie\Once\Backtrace;
use Spatie\Once\Cache;
if (!function_exists('only_once')) {
function only_once(callable $callback): mixed
{
$trace = debug_backtrace(
DEBUG_BACKTRACE_PROVIDE_OBJECT, 2
);
$backtrace = new Backtrace($trace);
if ($backtrace->getFunctionName() === 'eval') {
return call_user_func($callback);
}
$object = $backtrace->getObject();
$cache = Cache::getInstance();
if (is_string($object)) {
$object = $cache;
}
if (!$cache->isEnabled()) {
return call_user_func($callback, $backtrace->getArguments());
}
$hash = md5(
spl_object_hash($object)
. $backtrace->getObjectName()
. $backtrace->getFunctionName()
);
if (!$cache->has($object, $hash)) {
$result = call_user_func($callback, $backtrace->getArguments());
$cache->set($object, $hash, $result);
}
return $cache->get($object, $hash);
}
} |
Beta Was this translation helpful? Give feedback.
-
Hi @freekmurze,
I love the once package.
It really helped me on some performance issues in a legacy and spaghetti codebase.
But I noticed, that in some circumstances, once is not working as I was expecting it to do.
Let's take a look at the following example:
I thought I was fine with this, but then I saw, that once is creating the once-per-combination key by the arguments provided to the outer function. That means, if I call the
processSomethingHeavy
on 10000 users, of which a high percentage may have the same foo_relation_id, but all of them for sure have a different user_id, the cache will not work, cause the once-per-combination key gets generated by the outer function parameters. With this I would drastically lose performance here!Since PHP 8.1 you can dynamically get the parameters passed to a callback like this:
With that code we could generate the once-per-combination key from the parameters passed to the closure, which I think is much more intuitive and also as shown above would lead to a better cache hit and performance!
Cause I needed it fast, I wrote a own small memoization package.
But if you think about implementing this approach, I would definitly use the once package again!
Beta Was this translation helpful? Give feedback.
All reactions