Fortunately Fakoli provides a mechanism for handling this type of problem, via the process component. The process component allows you to respawn web requests as background processes that execute outside of the web server process. For the examples in this article I will use Fakoli's solr component, which provides full text indexing of documents in Fakoli document libraries. Indexing these documents can take time, depending on the size of the document libraries and the server resources available.
The first step in converting to a background process model is to take your action handler and modify it to perform the process spawn. Here is our original action handler, where all the SOLR indexing is performed in the web request:
Fakoli::using("solr");
$document_library_id = checkNumeric($_GET["document_library_id"]);
SolrManager::indexLibrary($document_library_id, true, $process);
To convert it to spawn a background process, we modify it as follows:
Fakoli::using("solr", "process");
$document_library_id = checkNumeric($_GET["document_library_id"]);
if (!$process)
{
// We are in a user request - spawn the background process and return the ID
$process = new ProcessManager();
echo $process->run("/action/solr/index_library?document_library_id=$document_library_id");
}
else
{
// We are in the spawned background process - begin indexing the library
SolrManager::indexLibrary($document_library_id, true, $process);
}
Once you have your background process running, you need to report back to the user periodically on how things are going. The ProcessManager object provides this functionality. The initial status of the process is "Starting". We set it to "Running" at the start of our computation, then send periodic updates. Finally when we are finished we set the status to "Completed".
$count = count($documents);
if ($process)
{
$process->setProgress("Running", "Indexing $count files", 0);
}
$c = 0;
foreach($documents as $document)
{
// ... Process the documents, then update the counter
++$c;
if ($process)
{
$process->setProgress("Running", "Indexing $c of $count", ($c * 100 / $count));
}
}
$process->setProcess("Completed", "All done!", 100);
Now we have all our background processing wired up, we just need to provide a progress UI to keep the user informed of what is happening. Fakoli makes this pretty simple, using a Javascript class called BackgroundProcess(). Here is how we would set up a background process call from a button in our HTML:
<a class='button' href='#'
onclick='new BackgroundProcess("Indexing Library",
"/action/solr/index_library?document_library_id=1",
{onComplete: function() { window.location.reload(); } });
return false;'>Index Files</a>
The Javascript object manages the whole process of displaying a modal popup with a progress bar, and then calling your onComplete action once the background process has completed. The UI looks like this:
Every once in a while you'll run across something like a long-running report, or a computationally intensive activity that you will need to handle in this fashion. And now you can, thanks to Fakoli.