3

I'm writing a simple code to simply show to clients, data that is actually loaded from another HTTP server. The problem is that loading it from the remote server can take up to multiple seconds, and I don't want that much page load delay. So, I make my server cache a copy of this data. So that whenever a client sends a request to my server, it sends the ready-loaded copy and then loads a new copy from the remote server to update the local copy in case any changes were made.

So here's my pseudo code:

if(file_exists($cache_path)){
    echo file_get_contents($cache_path);
    // I need to end the HTTP request and close the connection here while continuing with the code.
    $uptodate_content = file_get_contents("https://docs.google.com/document/export?format=pdf&id=$id");
    // I don't want the user to wait for nothing, until this line.
}
else {
    $uptodate_content = file_get_contents("https://someremotehost.com/someresource");
    echo $uptodate_content;
}
echo file_put_contents($cache_path, $uptodate_content);
3
  • You should run it in a background process instead Commented Dec 23, 2020 at 14:11
  • Sounds strange, delivering an outdated copy only to then, afterwards fetch the more current version... Wouldn't it make much more sense to use client side logic to fetch the resource and demonstrate in a transparent manner that the fetching process is idling? Commented Dec 23, 2020 at 14:13
  • Also you should read about "etag"s and how they help to check if a resource has actually changed or not. Commented Dec 23, 2020 at 14:13

3 Answers 3

1

Hi
I think the best solution is using a queue
For example if you use the the queue, you can send it to the queue and then your consumer can pick it from the queue when it has time and user do not need to wait for it
This link is helpful
And this link will help you to use redis for this problem

Sign up to request clarification or add additional context in comments.

Comments

0

This is a bad practice. The connection can never end and you should be careful with such code The better method is to run a cron job/queue every houerget data from remote server, or alternatively the remote server will trigger a trigger when updating data.

<?php
 ob_end_clean();
 header("Connection: close");
 ignore_user_abort(); 
 ob_start();
 //your code
 //your code
 //your code
 echo "response foo bar";
 $obSize = ob_get_length();
 header("Content-Length: $obSize");
 ob_end_flush(); 
 flush();           
 session_write_close(); 

 // Do processing here 
 request_to_remote_server();

Comments

0

One way of doing it:

First, create a new PHP file, let's call it update.php, and write the following:

if (isset($argv[1])) {
    storeDocumentToCache($argv[1]);
}

And in your current file, change the code to:

echo readDocumentFromCache($id) ?? storeDocumentToCache($id);

In old PHP versions (<7) it should be:

$content = readDocumentFromCache($id);
echo isset($content) ? $content : storeDocumentToCache($id);

Then require the following helper functions in both files (and set $cache_path):

function readDocumentFromCache($id, $fetch = true)
{
    $cache_path = "?";
    
    if (file_exists($cache_path)) {
        return file_get_contents($cache_path);
    }
    
    if ($fetch) {
        execInBackground("php " . __DIR__ . "/update.php $id");
    }
    
    return null;
}

funciton storeDocumentToCache($id)
{
    $cache_path = "?";

    $uptodate_content = file_get_contents("https://docs.google.com/document/export?format=pdf&id=$id");

    file_put_contents($cache_path, $uptodate_content);
    
    return $uptodate_content;
}

function execInBackground($cmd)
{
    if (substr(php_uname(), 0, 7) == "Windows") {
        pclose(popen("start /B " . $cmd, "r"));
    } else {
        exec($cmd . ' > /dev/null 2>/dev/null &');
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.