Jump to content

Rest API caching


Recommended Posts

<?php
              $myData = file_get_contents("");
              $myObject = json_decode($myData);
              $myObjectMap = $myObject->result;
            ?>

can i somehow build in that it only request every 5 minutes because if there are many users on the site it request too much?

Link to post
Share on other sites

Every time you make the call, store the time. Then compare it before you make the next call - if it's been less than 5 minutes, use the existing data. Otherwise make the call again. Or you can use Redis with a 5 minute TTL - if the index exists, use it. If not, refresh it.

Link to post
Share on other sites
4 hours ago, maxxd said:

Every time you make the call, store the time. Then compare it before you make the next call - if it's been less than 5 minutes, use the existing data. Otherwise make the call again. Or you can use Redis with a 5 minute TTL - if the index exists, use it. If not, refresh it.

@maxxd Do you know how can I do this with Redis or test this with microtime?

 

Edited by Guest
Link to post
Share on other sites

I'd probably store the last time the API call was run in a Redis key, then check against it before running the next call. Honestly I'm not sure that setting a 5 minute TTL on a Redis key will delete the key after 5 minutes (I think it will, but I'm not completely sure and if it's important you shouldn't mess about with it), so it's probably safer to just create a key and update it every time the API call is made.

Link to post
Share on other sites

Pseudocode:

$lastCall = Redis::get('API::CALL::LAST');
if(empty($lastCall) || microtime() - $lastCall > (5 * 60 * 1000)){
	$this->apiReturn = makeApiCall();
	Redis::set('API::CALL::LAST', microtime());
	return $this->apiReturn;
}
return $this->apiReturn;
Edited by maxxd
Link to post
Share on other sites
7 hours ago, maxxd said:

Pseudocode:



$lastCall = Redis::get('API::CALL::LAST');
if(empty($lastCall) || microtime() - $lastCall > (5 * 60 * 1000)){
	$this->apiReturn = makeApiCall();
	Redis::set('API::CALL::LAST', microtime());
	return $this->apiReturn;
}
return $this->apiReturn;

Can you adapt this to my code, because I'm not familiar with redis would be very helpful @maxxd

Edited by Guest
Link to post
Share on other sites

Here are a couple links on using Redis - it's super simple. https://redislabs.com/lp/php-redis/ and https://github.com/phpredis/phpredis.

Long story short, I'm not going to write your code for you. The point of this board is to help people when they get stuck with the code they're writing - I feel I've done that in this case. Take what you know and what I suggested and try to write it. If you have problems then, post the code you've written and we can all take another look. But you're not going to learn anything if I write the code for you.

Link to post
Share on other sites

Redis requires an external server to be running that you communicate with.  If you don't already have a redis server running, the easiest thing to do would probably be to just store the cached data in a file on the server or in your database if you have one.  The basic premise is the same though, you store the time along with the data when you run your API call.  Before subsequent calls you check if the time since the last call has exceeded some threshold. 

To do this with a file you might follow these steps:

  1. Designate a particular file as your cache, store it's name in a variable.
  2. Check if that file exists.
  3. If it does not exist go to step 8 otherwise continue.
  4. Get the time it was last modified.
  5. Get the current time.
  6. Get the duration since last call by subtracting the last modified time from the current time.
  7. If the duration is less than your threshold go to step 10 otherwise continue.
  8. Perform your API call.
  9. Store the results in your cache file.
  10. Read the results of the last API call from your cache file.

 

Link to post
Share on other sites
<?php 
   $redis = new Redis(); 
   $redis->connect('127.0.0.1', 6379); 
   echo "Connection to server sucessfully"; 
   $lastCall = Redis::get('API::CALL::LAST');
    if(empty($lastCall) || microtime() - $lastCall > (5 * 60 * 1000)){
	    $this->apiReturn = makeApiCall();
	    Redis::set('API::CALL::LAST', microtime());
	    return $this->apiReturn;
    }
   return $this->apiReturn;  
?>

But I do not understand where I should enter my things now

Link to post
Share on other sites

if you dont have a redis server running, stick to using a file with the functions provided by @kicken - the logic is pretty easy

# pseudo code
if(file_age > 5 minutes) save api data to file;
get data from file;

 

Link to post
Share on other sites
9 minutes ago, Endrick said:

but i don't understand how i should use my data

You do basically the same steps I outlined above for using a file, except you use redis instead.  You designate a specific key to hold your API call results.  Before doing your API call check if that key already has a value or not.

Rather than DIY it, you could use a pre-made caching solution to make things simpler.

$client = new Redis();
$client->connect('127.0.0.1', 6379);
$cache = new RedisCachePool($client);

$ttl = 300;
$key = 'apiCache';
$results = $cache->get($key);
if ($results === null){
    $results = doYourApiCall();
    $cache->set($key, $results, $ttl);
}

//Do whatever with $results

 

Link to post
Share on other sites
3 hours ago, kicken said:

Rather than DIY it, you could use a pre-made caching solution to make things simpler.

Which is why I recommended Redis to begin with. Honestly, I kinda assumed it was a standard default in host/VPN setups (which may tell you how out of touch I am with devOps and server admin).

Link to post
Share on other sites
On 11/23/2020 at 11:20 PM, maxxd said:

Which is why I recommended Redis to begin with. Honestly, I kinda assumed it was a standard default in host/VPN setups (which may tell you how out of touch I am with devOps and server admin).

@maxxd unfortunately after several attempts to rewrite the code it still does not work

 

Edited by Guest
Link to post
Share on other sites

This is entirely untested, but using the snippet of code you posted first and the statement that you've got a running Redis server, try this:

function doSomeStuff(){
	try{
		$redis = new Redis(); 
	}catch(RedisException $e){
		die('Could not connect to Redis host');
	}

	if(!$redis->connect('127.0.0.1', 6379)){
		die('Redis connection failed');
	}

	$lastCall = $redis->get('API::CALL::LAST');

	if(empty($lastCall) || microtime() - $lastCall > (5 * 60 * 1000)){
		$myData = file_get_contents('');
		$myObject = json_decode($myData);
		
		if(!is_null($myObject)){
			$myObjectMap = $myObject->result;

			$redis->set('API::CALL::LAST', microtime());
			return $myObjectMap;
		}
	}
	return false;
}

$stuff = doSomeStuff();

 

Link to post
Share on other sites
<?php
function doSomeStuff(){
	try{
		$redis = new Redis(); 
	}catch(RedisException $e){
		die('Could not connect to Redis host');
	}

	if(!$redis->connect('127.0.0.1', 6379)){
		die('Redis connection failed');
	}

	$lastCall = $redis->get('API::CALL::LAST');

	if(empty($lastCall) || microtime() - $lastCall > (5 * 60 * 1000)){
		$myData = file_get_contents('apiurl');
		$myObject = json_decode($myData);
		
		if(!is_null($myObject)){
			$myObjectMap = $myObject->result;
       $firstObj = $myObjectMap[0]; 
       $money = $firstObj->Money;
       
			$redis->set('API::CALL::LAST', microtime());
			return $myObjectMap;
		}
	}
	return false;
}

$stuff = doSomeStuff();
$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY); 
       echo $fmt->formatCurrency($money, "EUR")."\n";  
?>

I get only 0 euro although the api actually contains a different number @maxxd

Edited by Guest
Link to post
Share on other sites

I'm sure it does, because you copied and pasted my code and then didn't use it. If you had error reporting turned on you'd be getting an error about the fact that $money doesn't actually exist. You may not know how to code, but you can obviously read. Apply some though to what you're seeing here and adapt the code that you've got with the code you've been given.

Link to post
Share on other sites

I get displayed A non well formed numeric value encountered in this line:

if(empty($lastCall) || microtime() - $lastCall > (5 * 60 * 1000)){

@maxxd

Edited by Guest
Link to post
Share on other sites

I don't mean to be rude, but you're going to have to do some work on your own, here. Again, I'm not writing this for you - what's the value of $lastCall? Echo it out, explore what the code's doing. If nothing else has changed in the code you posted, it doesn't matter because you don't actually use the code that I gave you.

Link to post
Share on other sites
16 minutes ago, maxxd said:

How so?

Have you considered RTFM?

Quote

Return Values

By default, microtime() returns a string in the form "msec sec", where sec is the number of seconds since the Unix epoch (0:00:00 January 1,1970 GMT), and msec measures microseconds that have elapsed since sec and is also expressed in seconds.

 

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.