yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.24k stars 6.91k forks source link

fileCache expire not set #20241

Closed nikdow closed 1 month ago

nikdow commented 1 month ago

What steps will reproduce the problem?

Yii component: 'cache' => [ 'class' => 'yii\caching\FileCache', ], Set cache: Yii::$app->cache->set(self::ACCESS_TOKEN_CACHE_KEY, $accessToken, $expiresIn - 60); Get cache: $cachedToken = Yii::$app->cache->get(self::ACCESS_TOKEN_CACHE_KEY);

What is the expected result?

Cache should expire: $expiresIn - 60

What do you get instead?

Cache does not expire

Additional info

used grep -R expire * on cache files on server. Only results are Yii db schema caching. No results from our Access Token caching. Seems that the above calls are not setting an expire time on the file cache.

Have been logging cache use to check expire time is set as expected. We see the expire time is passed as above, and we see cache requests returning a value many hours after expire time.

Q A
Yii version 2.0.50
PHP version 8.2 (fpm)
Operating system Linux 5.15.0-88-generic #98-Ubuntu SMP Mon Oct 2 15:18:56 UTC 2023 x86_64
bizley commented 1 month ago

File cache expiration time is stored in the modification time of the file itself, not in the file's content.

Please double check if your Yii::$app->cache->set() returns true otherwise it indicates that something is wrong.

nikdow commented 1 month ago

Thanks for that clue about fileCache. Here's what I think is happening. We run about 70 instances of a SaaS system, all sharing the same apache webroot, i.e. running the same source code (with occasional exceptions). The runtime directory is the same for all instances. fileCache is therefore shared between the instances. I'm guessing that when we call Yii::$app->cache->set(self::ACCESS_TOKEN_CACHE_KEY, $accessToken, $expiresIn - 60); that is overwriting or updating the same file regardless of which instance is running. A bit of our code not included above: const ACCESS_TOKEN_CACHE_KEY = 'paypal:access_token'; so the Cache Key is the same for all instances. I switched the cache call to use dbCache and the problem disappears, because each instance uses a different database. Our application defines two Yii components for caching, the fileCache is shown in the code in my first post, we also have: 'dbCache' => [ 'class' => 'yii\caching\DbCache' ],
and dbCache is used by our application for all other caching purposes. We slipped up by using fileCache for this one purpose.

Noted that Yii uses file cache for model schema, this is mostly OK when the instances all share the same database schema and probably saves some processing time because Yii finds schema already cached by a different instance. The exception would be occasions when we run a different release on some instances (i.e. the instance gets pointed to a different webroot), which may have differences in the db schema. So I will keep that in mind if we get a schema related bug in this situation.