Closed ShockedPlot7560 closed 2 years ago
Hello curious contributor ! Since it seems to be your first contribution, make sure that you've been:
I have the same issue with Memcached driver.
PHP Fatal error: Uncaught TypeError: Phpfastcache\Drivers\Memcached\Driver::driverRead(): Return value must be of type ?array, string returned in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php:154
Stack trace:
#0 /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php(132): Phpfastcache\Drivers\Memcached\Driver->driverRead()
#1 /public_html/controller/Controller.php(61): Phpfastcache\Drivers\Memcached\Driver->getItem()
...
#4 {main}
thrown in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php on line 154
This behavior is very surprising as all tests would have been broken if such behavior would happens.
Did you decorated Phpfastcache services or something ?
If you see in /tests
lot of call to getItem are made, especially with Files
driver.
(See ReadWriteOperations.test.php)
Can you please post your full code implementation below ?
Because this is the very first time report me this kind of issue that should be impossible to produce, especially with LOT of tests calling getItem()
.
I have the same issue with Memcached driver.
* **PhpFastCache version:** 9.1.0 * **PHP version:** 8.0.17 * **Operating system:** Ubuntu
PHP Fatal error: Uncaught TypeError: Phpfastcache\Drivers\Memcached\Driver::driverRead(): Return value must be of type ?array, string returned in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php:154 Stack trace: #0 /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php(132): Phpfastcache\Drivers\Memcached\Driver->driverRead() #1 /public_html/controller/Controller.php(61): Phpfastcache\Drivers\Memcached\Driver->getItem() ... #4 {main} thrown in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php on line 154
Can't reproduce it neither, I'm gonna need more information with your full code implementation.
For confidentiality you can send me sensible code at contact at geolim4.com
Hello,
The error also seems very strange to me and never happens in local but only in production.
I will detail below the architecture likely to make a bug and will take the simplest case which brings me this error :
Before anything, I use the PHP-DI container for dependency injection that I build like this:
$buildeur = new ContainerBuilder();
$buildeur->addDefinitions($pathToConfigFile);
$buildeur->enableCompilation(__ROOT_FOLDER . "/tmp");
$container = $buildeur->build();
The configuration file is of type:
<?php
use DI\Container;
use Phpfastcache\CacheManager;
use Phpfastcache\Config\ConfigurationOption;
require __ROOT_FOLDER . "/vendor/autoload.php";
return [
CacheManager::class => function (Container $container) {
$instance = $container->get("ENV") === "dev" ? "Devnull" : "files";
CacheManager::setDefaultConfig(new ConfigurationOption([
"path" => $container->get("tmp.path")
]));
return CacheManager::getInstance($instance);
}
];
After that, so the compilation of the container has been defined, and phpfastcache and DI share the same tmp/ directory.
A case that I have a problem with is going to be below. Or, the code that seems to be problematic anyway, a very trivial value retrieval and saving code.
//I have simplified the operation and removed the portions of code that are not necessary and do not interfere
$pdo = $container->get(PDO::class);
/** @var ExtendedCacheItemPoolInterface */
$cacheManager = $container->get(CacheManager::class);
$cacheString = "Maintenance";
$cacheItem = $cacheManager->getItem($cacheString);
if ($config["maintenance"] !== true && $pdo !== null) {
$cacheItem->set(false)->expiresAfter(3600 * 24);
$cacheManager->save($cacheItem);
} else {
if($pdo === null){
if($cacheItem->get() === false || $cacheItem->get() === null){
// send notification to discord
}
if(!$cacheItem->isHit()){
$cacheItem->set(true)->expiresAfter(3600 * 24);
}
$cacheManager->save($cacheItem);
}
}
I think you are facing race condition issue with Files
driver.
Try to enable the option preventCacheSlams
(only for Files
driver), see Wiki.
Also I suggest you a better approach with the CacheManager.
Instead of calling:
CacheManager::setDefaultConfig(new ConfigurationOption([
"path" => $container->get("tmp.path")
]));
Try to do:
return CacheManager::getInstance($instance, [
'path' => $container->get("tmp.path"),
'preventCacheSlams' => true,
]);
// OR
Also try a more performant driver like Redis
if you can, this will be more appropriated for heavy cache usage.
I'll try your answer, however regarding the Redis driver, it takes, I guess a lot of memory space?
Not at all, redis is one of the lightweight memory backend I know. It is popular because of its efficiency and few ressources needed ๐
But first try to enable the option I suggested above.
Update after testing in production (where it crashes). The error is always launched having set the configuration as requested. I will try to switch to the Redis driver to see if it still happens or not.
How many request per second do you have ?
Can you invit me to talk on discord maybe ? :)
This can go up I think to 10/15 requests per second at most. They are then limited by the capacity of my proxy and the traffic.
Of course, here is my discord: ShockedPlot7560 # 9999
Added you, so we can discuss more clearly about your issue !
I have the same issue with Memcached driver.
* **PhpFastCache version:** 9.1.0 * **PHP version:** 8.0.17 * **Operating system:** Ubuntu
PHP Fatal error: Uncaught TypeError: Phpfastcache\Drivers\Memcached\Driver::driverRead(): Return value must be of type ?array, string returned in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php:154 Stack trace: #0 /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php(132): Phpfastcache\Drivers\Memcached\Driver->driverRead() #1 /public_html/controller/Controller.php(61): Phpfastcache\Drivers\Memcached\Driver->getItem() ... #4 {main} thrown in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php on line 154
I need more information @aemla. What is the string returned exactly ? Can you dump me the content of that string please ? Because unlike @ShockedPlot7560 I can't reproduce your issue.
I have the same issue with Memcached driver.
* **PhpFastCache version:** 9.1.0 * **PHP version:** 8.0.17 * **Operating system:** Ubuntu
PHP Fatal error: Uncaught TypeError: Phpfastcache\Drivers\Memcached\Driver::driverRead(): Return value must be of type ?array, string returned in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php:154 Stack trace: #0 /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php(132): Phpfastcache\Drivers\Memcached\Driver->driverRead() #1 /public_html/controller/Controller.php(61): Phpfastcache\Drivers\Memcached\Driver->getItem() ... #4 {main} thrown in /public_html/vendor/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Memcached/Driver.php on line 154
I need more information @aemla. What is the string returned exactly ? Can you dump me the content of that string please ? Because unlike @ShockedPlot7560 I can't reproduce your issue.
It can be reproduced by running it in a loop. I wrote a little example, it doesn't make any sense, but it throws the same error. ๐ In my original code, I am getting data from a database. I am getting this error only with the Memcached driver. Files driver works fine.
Dump of that string:
string(0) ""
function test()
{
$array = [
['userId' => 1, 'data' => 'test'],
['userId' => 2, 'data' => 'test'],
['userId' => 3, 'data' => 'test'],
['userId' => 4, 'data' => 'test'],
['userId' => 5, 'data' => 'test'],
['userId' => 6, 'data' => 'test'],
['userId' => 7, 'data' => 'test'],
['userId' => 8, 'data' => 'test'],
['userId' => 9, 'data' => 'test'],
['userId' => 10, 'data' => 'test'],
['userId' => 11, 'data' => 'test'],
['userId' => 12, 'data' => 'test'],
['userId' => 13, 'data' => 'test'],
['userId' => 14, 'data' => 'test'],
['userId' => 15, 'data' => 'test'],
['userId' => 16, 'data' => 'test'],
['userId' => 17, 'data' => 'test'],
['userId' => 18, 'data' => 'test'],
['userId' => 19, 'data' => 'test'],
['userId' => 20, 'data' => 'test'],
['userId' => 21, 'data' => 'test'],
['userId' => 22, 'data' => 'test'],
];
$cache = CacheManager::getInstance('Memcached');
// The error only occurs when writing to the cache, so let's clear it before running the loop.
$cache->clear();
foreach ($array as $row) {
$this->getFromCache($cache, $row['userId'], $row['data']);
}
}
function getFromCache(ExtendedCacheItemPoolInterface $cache, $userId, $data)
{
$cachedString = $cache->getItem('dataById=' . $userId);
if (!$cachedString->isHit()) {
$cachedString->set($data)->expiresAfter(300);
$cache->save($cachedString);
return $cachedString->get();
} else {
return $cachedString->get();
}
}
I ran your code sample:
And I have no error at all, so I can't reproduce your bug :/
What version of php-memcached version are you using ? Do you run multiple concurrent process ?
This error occurs only in 9.x, it works fine in 8.x. I am using LSMCD https://github.com/litespeedtech/lsmcd could this be the reason why it sometimes returns an empty string?
This issue can be fixed by adding a check for an empty string.
/**
* @param ExtendedCacheItemInterface $item
* @return null|array
*/
protected function driverRead(ExtendedCacheItemInterface $item): ?array
{
$val = $this->instance->get($item->getKey());
if ($val === false || $val === โโ) {
return null;
}
return $val;
}
"it works fine in 8.x" ?
That's interesting. Did you tried in v8.1.x or previous one ?
I understand now, I typed driverRead
with ?array
as of v9.
Ok ok, that make sense now.
v8 was workin well because I previously made a weak validation: https://github.com/PHPSocialNetwork/phpfastcache/blob/894421d73b8aa1eb839553cfcb3201be13ecda90/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php#L139
But as of v9 I introduced (very) strict types everywhere this one can be problematic under some circumstances.
Just out of curiosity tell me if replacing:
if ($val === false) {
return null;
}
by
if (empty($val) || !\is_array($val)) {
return null;
}
fixes your issue ?
Just out of curiosity tell me if replacing:
if ($val === false) { return null; }
by
if (empty($val) || !\is_array($val)) { return null; }
fixes your issue ?
Yes, now it works fine.
Roger that. I'll push a fix tonight and make a new release by the end of the week at late.
Hi,
we are still getting the same error. We are using version 9.1.2 and php 8.1.
PHP Fatal error: Uncaught TypeError: Phpfastcache\Drivers\Files\Driver::driverRead(): Return value must be of type ?array, bool returned in /var/www/prod/app/vendor8/phpfastcache/phpfastcache/lib/Phpfastcache/Drivers/Files/Driver.php:74
Stack trace:
#0 /var/www/prod/app/vendor8/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php(143): Phpfastcache\Drivers\Files\Driver->driverRead()
#1 /var/www/prod/app/vendor8/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php(106): Phpfastcache\Drivers\Files\Driver->getItem()
#2 /var/www/prod/app/vendor8/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/TaggableCacheItemPoolTrait.php(399): Phpfastcache\Drivers\Files\Driver->getItems()
#3 /var/www/prod/app/vendor8/phpfastcache/phpfastcache/lib/Phpfastcache/Core/Pool/CacheItemPoolTrait.php(386): Phpfastcache\Drivers\Files\Driver->driverWriteTags()
#4 /var/www/prod/app/library/App/Cache/Cache.php(76): Phpfastcache\Drivers\Files\Driver->save()
Any tip?
You seem to have concurrency issue as the file exists on disk but looks empty, very weird.
Did you tried to enable preventCacheSlams
option ?
will try and I report back.
We have tried it and we still get the same error. I think the problem is in decode() function when calling unserialize() which one return false when it cant unserialize a string.
Then you have a serious problem of I/O with your disk this is is not supposed to happens unless the file are corrupted or partially written which is a sign of a failing disk. I have multiple tests with this driver on the CI including concurrent writes and I'm not encountering this kind of issue.
The problem is that this happens on multiple different servers and I really doubt that all servers have disk issues ๐
now we have tired to set setSecureFileManipulation()
and it looks good.
Configuration
Describe the bug
I don't really know the nature of the bug, but it seems to come from the File driver
Phpfastcache\Drivers\Files\Driver::driverRead()
To Reproduce Code to reproduce the issue:
Driver used :
files
Stacktrace