chrizz Posted October 27, 2021 Share Posted October 27, 2021 maybe it's to late, maybe I am just overseeing an important detail. I have read the docs for WireCache multiple times, I have debugged a lot but for some reason I cannot find a useful explanation and I am starting to feel concerned that my use case isn't even covered by WireCache. Using a expire date during the get requests leads to the desired result only if the original expire date (during save) was lower. This one way approach seems to make ithe following impossible: What I want to achieve: I want to store data in cache retrieved from an external API make sure that data is always present, even if the API is down: I set the expire date during cache->save() to 1 month cached data is retrieved via $cache->get("cacheName") without an explicit expireDate (means: it expires in a month) a cronjob should update this cache on a 5-minute basis. Therefore I am trying to get the cached data via $cache->get("cacheName", (5*60)) Unfortunately it seems as if this cannot be achieved with the WireCache implementation, because lower expireDates during the ->get will *always* result in a "cache miss". It seems that what would help me is a creation timestamp for a cache entry which could be checked as well. The more I think about the more I come to the conclusion that this kind of "two-expire-dates" isn't coverable with WireCache Do I oversee something or is this known/wanted behavior? some code in case you want to try it on your own: $this->cache->save("cachetest","abc", 10); echo "1: <pre>".print_r($this->cache->get("cachetest"),true)."</pre>"; echo "2: <pre>".print_r($this->cache->get("cachetest", 5),true)."</pre>"; echo "3: <pre>".print_r($this->cache->get("cachetest", 30),true)."</pre>"; sleep(15); echo "4: <pre>".print_r($this->cache->get("cachetest"),true)."</pre>"; echo "5: <pre>".print_r($this->cache->get("cachetest", 5),true)."</pre>"; echo "6: <pre>".print_r($this->cache->get("cachetest", 30),true)."</pre>"; Output: 1: abc 2: 3: abc 4: 5: abc 6: abc I would have expected that number 2 would result in a cache hit, because the expire date is still 5s in the future. Link to comment Share on other sites More sharing options...
BitPoet Posted October 28, 2021 Share Posted October 28, 2021 The short answer is: don't use a lifetime in calls to $cache->get(). Somewhat longer: it looks like a bug to me. It certainly doesn't do what the docs say, namely check the age of an entry. The behavior is a bit different if you specify a template function as the third value, as that uses the lifetime to fill the cache with the function's return value, but that's neither here nor there. In your case (unless I'm misinterpreting what you wrote), the only call that needs a lifetime is the one to $cache->save() in your cron job. The other parts can just call $cache->get('cachetest') and be happy (unless the cache wasn't updated within the last month). 1 Link to comment Share on other sites More sharing options...
chrizz Posted October 28, 2021 Author Share Posted October 28, 2021 to me it looks like a bug as well, but I didn't mention it yesterday because I didn't even know what exactly to expect ? Using the lifetime only during save could lead to unwanted behavior, that the cache is gone during the get request (e.g. the API is down for longer than 5min). That's why I would need some kind of fallback... So basically: * GET logic: use always data from cache * SAVE: retrieve data from API and save to cache if last save is > 5min I think I will go another way, ignoring the cache capabilites and use pages instead. Nevertheless: thanks for your input ? Link to comment Share on other sites More sharing options...
BitPoet Posted November 5, 2021 Share Posted November 5, 2021 On 10/28/2021 at 5:08 PM, chrizz said: Using the lifetime only during save could lead to unwanted behavior, that the cache is gone during the get request (e.g. the API is down for longer than 5min). That's why I would need some kind of fallback... So basically: * GET logic: use always data from cache * SAVE: retrieve data from API and save to cache if last save is > 5min Why don't you split your cron job's logic to use two separate cache calls? $cache->get('cachetest') to read your cached data without expiring it, and $cache->save('cachetest', '+1 month', $apiresult) only if your api call was successful. You'll always have the last successful call's result in your cache this way, and it will be much cheaper than full fledged pages. Link to comment Share on other sites More sharing options...
chrizz Posted November 30, 2021 Author Share Posted November 30, 2021 On 11/5/2021 at 7:56 AM, BitPoet said: Why don't you split your cron job's logic to use two separate cache calls? $cache->get('cachetest') to read your cached data without expiring it, and $cache->save('cachetest', '+1 month', $apiresult) only if your api call was successful. You'll always have the last successful call's result in your cache this way, and it will be much cheaper than full fledged pages. are you sure that this would work? In the test I did above, the value wasn't returned from cache once the cache has expired echo "4: <pre>".print_r($this->cache->get("cachetest"),true)."</pre>"; Link to comment Share on other sites More sharing options...
BitPoet Posted December 2, 2021 Share Posted December 2, 2021 On 11/30/2021 at 8:34 PM, chrizz said: are you sure that this would work? In the test I did above, the value wasn't returned from cache once the cache has expired I think we've talking past each other a bit, so let me see if I can word it differently. The cache should never return an expired value, but I can understand that the strange behavior in your tests 5 and 6 suggests differently. If you don't want to lose a value, don't let it expire. Instead, put the logic to overwrite the cached value with a newer one when your API call is successful into your code. And perhaps store the last retrieval time in your cached value, so you have the creation timestamp you mentioned. Perhaps code says more than a thousand words: <?php /** * Code for Cron Job */ $apiResult = your_api_call(); $cachedResult = json_decode($cache->get('yourcachekey'), true); if($apiResult) // Only if API call was successful if(!$cachedResult || $cachedResult['created'] < time() - 300) { // Cache entry older than 5 minutes, write new value to cache $cache->save('yourcachekey', json_encode(['created' => time(), 'apiResult' => $apiResult], WireCache::expireNever); } } /** * Code for frontend use of API data */ $cachedResult = json_decode($cache->get('yourcachekey'), true); $apiResult = $cachedResult['apiResult']; if($apiResult['created'] < strtotime('-1 month')) { // Deal with a stale cache value that hasn't been updated in over a month here } 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now