Jump to content

Checking whether $cache is expired OR doesn't exist


a-ok
 Share

Recommended Posts

Regarding the `$cache` API I need to check whether the cache requested has either expired OR doesn't exist.

Normally I just do this usual check which creates the cache if the get method returns null or doesn't exist:

$result = wire('cache')->get('instagramFeed', 3600);
if (!$result) {
	$result = $instagramHttp->getJSON($instagramBase);
	wire('cache')->save('instagramFeed', $result, 3600); // Expire every hour
}

I need to store an access token in the cache also, which expires every month. However, I need to do a check whether the cache is expired (and run a query to fetch and store a new one) OR if it simply didn't exist (which in theory would only be called once to initiate the cache) which would populate it with a static token.

I read this in the docs:

Quote

If cache exists and is older, then blank returned. You may omit this to divert to whatever expiration was specified at save() time. Note: The $expire and $func arguments may optionally be reversed.

Am I right in thinking if I call `wire('cache')->get('instagramFeed', 3600);` and the cache exists but is expired it wouldn't return null but rather an empty string? But if the cache doesn't exist then it returns null? And therefore I could do a check like so?

$instagramHttp = new WireHttp();
$instagramAccessToken = wire('cache')->get('instagramAccessToken', WireCache::expireMonthly);
if (!$instagramAccessToken) { // null = doesn't exist = use static token
	$instagramAccessToken = '123456789010';
} else { // 'blank' assumed expired
	$instagramAccessToken = $instagramHttp->getJSON("https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=$instagramAccessToken")
}

 

Link to comment
Share on other sites

I don't completely get your use-case; what use is a static token in this situation? But anyway ...

Instead of relying on some flaky edge cases of the $cache API (like returning null vs an empty string, which could change at some point), I would just explicitly store the information you need in a separate place. If your instagram tokens are associated with pages or user accounts, you can have something like a has_token field in addition to the token itself. Or just save that information in the cache as well, but with no expiration date. So the first time the token is created, you could do something like this:

$instagramToken = 'your-token';
$cache->save('instagramAccessToken', $instagramToken, WireCache::expireMonthly);
$cache->save('instagramAccessTokenExists', '1', WireCache::expireReserved);

Then you can check if instagramAccessTokenExists is set in the cache, which will tell if you the token was previously saved to the cache, even if has expired. Note the use of WireCache::expireReserved, which makes that value as persistent as you can get with the cache API.

Link to comment
Share on other sites

Thanks @MoritzLost for the reply!
 

The token is simply one token for the whole API that expires every 60 days. If you refresh the token, before it expires, it gives you a new token, otherwise you have to go through the pain in the ass Facebook OG process setting up a token again.

The initI’ll token, which I get manually, has to be set first and after 30 days (to give the 60 days expiry some cushion!) it should run the refresh call and replace it. And so forth.

I guess I could just set up the cache with the init API manually, without it being programmatic, and then just run the usual  expiry test but I thought it would be nice to have it work from the get go.

Also I guess another issue is when it expires it needs to run the refresh call with the token that’s due to expire but at that point it will have already expired in the cache and therefore not exist...

 

Link to comment
Share on other sites

Ok, I understand the problem now. I still think your issue comes from trying to fit too much information into a single cache entry. With all those conditions for initial setup, token refresh etc you are talking about multiple distinct pieces of state, at least:

  • The initial token, set manually.
  • The refreshed token, set programmatically.
  • The expiration time for the currently used token.

You should definitely store those separately to have the fine control you require. I also wouldn't use the expiration time of the $cache API to represent the lifetime of the token – as you said, that becomes problematic when you need to refresh a token after it's expired (in the cache). Why not store this state in regular pages? Could be hidden pages that represent tokens and their lifetimes – or a hidden field on a global settings page. Anything that's more persistent than cache entries. And this will provide you with the interface to set the initial token. But if absolutely want to use the $cache API, I'd use separate entries for the above pieces of state and set those to expireNever or better yet, expireReserved. You wouldn't want your Facebook token to disappear because someone clicked on Clear all caches, after all ?

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...