I'm working on a project where I pull data (JSON) from an API. I would like to manipulate this data and store this as useful information in my DB (MySQL). My code is working if I would like to make, for example 2000 requests.
My script step by step:
- Get IDS from DB, store them in array urls.
- Take a chunk
- Set and execute multi cURL
- Check for error
- Manipulate data
- Store Data
- Merge urls that should be requested again
Now my problem, when I make around 4000+ request I get after 400 loops the fatal error:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20268759 bytes) in C:... on line 586
Of course I could increase the allowed memory size, but that is just a temporary fix. Because I can't keep increasing the size when the number of request increase.
I have been playing around with memory_get_usage()
& memory_get_peak_usage()
And see that both are increasing slowly. Until memory_get_peak_usage()
almost reaches the allowed size and then I get the error.
As I see it the memory-usage shouldn't be increasing, every loop I do the same and the variables are overwritten. So my question is: What am I doing wrong? How can I find the problem and how do I fix it? Do you see any major error in my code?
<?php
include ('connect.php');
set_time_limit(0);
$api_key = '***';
$ids = mysqli_query($connect, "SELECT Id FROM `table` LIMIT 2000");
$urls = array();
while($result = mysqli_fetch_array($ids))
{
$urls[] = 'https://website.com/api/json/' . $ids['id'] . '?api_key=' . $api_key;
}
//number of urls called simultaneously
$threads = 10;
//create the multiple cURL handle
$mh = curl_multi_init();
while($urls){
//take the first chunk ($threads) of all urls
$chunk = array_splice($urls, 0, $threads);
//create a cURL resource for all urls in this chunk
foreach($chunk AS $k => $url){
//create cURL resources
$ch[$k] = curl_init();
//set URL and other appropriate options
curl_setopt($ch[$k], CURLOPT_URL, $url);
curl_setopt($ch[$k], CURLOPT_RETURNTRANSFER, true );
curl_setopt($ch[$k], CURLOPT_SSL_VERIFYPEER, false);
//add the handles
curl_multi_add_handle($mh,$ch[$k]);
}
//execute the handles
do {
curl_multi_exec($mh, $running);
} while ($running);
//Return the content for all urls
foreach($chunk AS $k => $url){
$result = curl_multi_getcontent($ch[$k]);
//get info about the request
$error = curl_getinfo($ch[$k], CURLINFO_HTTP_CODE);
//error handling if not 200 ok code
if($error != 200){
//when its one of the following errors try again later.
if($error == 429 || $error == 500 || $error == 503 || $error == 504){
$again[] = $url;
} else {
$errors[] = array("Url" => $url, "errornbr" => $error);
}
//no errors
} else {
//parse the json
$decoded = json_decode($result,true);
//////////////////////////////
// Process/manipulate all data
//////////////////////////////
//query for the information
$$sqlInformation[] =
"('" .
$id ."','" .
$one . "','" .
$two . "','" .
$three . "','" .
...
"')";
$sql = "INSERT INTO `Information` (`id`, `one`, `two`, `three` ...)
VALUES " . implode(",",$sqlInformation) . "";
if (mysqli_query($connect, $sql)) {
echo "New information is created successfully";
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($connect);
}
curl_multi_remove_handle($mh, $ch[$k]);
curl_close($ch[$k]);
}
}
if(isset($again)){
$urls = array_merge($urls, $again);
unset($again);
}
//sleep, requestrate
sleep(10);
}
curl_multi_close($mh);
?>