PHP Classes
elePHPant
Icontem

Starting Long Server PHP Scripts and Monitor their Status Part 2: Solving the Problem with Classes - Asynchronous Long Server Tasks package blog

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  All package blogs All package blogs   Asynchronous Long Server Tasks Asynchronous Long Server Tasks   Blog Asynchronous Long Server Tasks package blog   RSS 1.0 feed RSS 2.0 feed   Blog Starting Long Server ...  
  Post a comment Post a comment   See comments See comments (4)   Trackbacks (0)  

Author: Joseluis Laso

Posted on:

Package: Asynchronous Long Server Tasks

In the first part of this article we have presented a solution to start tasks from PHP that take a long time to finish.

Read this article to learn how to implement the solution with the PHP class package named "Asynchronous Long Server Tasks".




Contents

Introduction

The Starter Class

The Status Class

A Real Example

How the Example Solution Works

Known Limitations

Trying to do More in Less Time Squeezing the Server


Introduction

Now that I have explained the solution for starting and monitoring server tasks that take a long time to finish in the first part of the article, lets talk about how I solved the problem with the package named Asynchronous Long Server Tasks.

The package consists of two main classes: one to start a task and on the other hand, another class to request the status of the task. Lets see how each of these classes work.

The Starter Class

The class that allow us to start a new task is the Starter.

The principle by which it works is simple. The task that we want to start has to be a script that responds to requests to a given URL, so it can be started sending a HTTP request to the script URL. Currently the class uses the curl command as a background process.

Why? It is pretty simple. We need to send the HTTP request and disconnect as soon as possible in order to not block on the browser and server side.

From the moment the task is started, the only way to know about the status task will be through the other class.

The Status Class

The status class is used by the task itself and by the script that will handle the request that the browser will do in order to obtain the progress of the task.

The task has to update the status every time progress of its actions changes. The browser invokes a little script in the server that uses that class and retrieve and return the status to the browser.

The package uses a file to store the status of the task in progress. Because both classes need to have knowledge about the real file to lock the task (semaphore) and the status file I have extended both from a common base class.

package structure

How to Use this Package?

Each task in the server have to be split in three parts:

  1. Script that starts the task
  2. Script that runs the task
  3. Script that requests the status

I have made these distinctions in order to have completely separated the logic of each part.

The scripts that start the task or get the status are pretty simple.  They have only to create an instance of Starter or Status classes and invoke them with the right parameters.

The main script is the one that runs the task has to include some things in order to do the task and maintain the status updated.

<?php

 set_time_limit(0);
 ignore_user_abort(true);

 // get the parameters
 $status = new Status(...);

 // the next lines terminates the output buffer and
 // let believe the  requester that the program had finished
 ob_start();

 // outputs anything you need to send to the requester
 header("Content-Length: ".ob_get_length());
 header('Connection: close');
 ob_end_flush();echoes
 flush();
 session_write_close();

 // this is a trick in order to copy the status file
 // if something wrong happens
 function master_shutdown()
 {
  global $status;

  $status->hangOn();
 }
 register_shutdown_function('master_shutdown');

 // the task process goes here

 // frees status file indicating that
 // this process has been terminated
 $status->freeStatusFile();

?>

As you may notice the real process happens at the end of the file. There is a lot of preparation in order to maintain the status updated, and the most important, there can only exist one instance of the task running at a given time.

The most important part is the one that disconnect the request, making believe the requester that the task has been finished. This way the whole process can continue without risk of being interrupted by timeout or some other problem.

Then the next thing to do is to get an instance of the Status class in order to maintain the task's status updated.

A Real Example

The script of example of usage presented here is pretty simple. The idea is to know how to start the task on the server and once started how to query its status.

Say that we have a document cloud storing service and we want to offer our user the possibility to send one or more of his files to another user.

The files are copied to the destination user's folder, so it is not a shared link. But we do not want to make wait the user until the of all his files.

At the same time could be a very good idea from the user experienced point of view to have a progress bar or something cool that shows to the user about the status of the task.

We are starting a little company and we do not have much money to have big server, so we work with smaller server instances. Maybe the files of one user are not in the same machine where are the other user files. So, the copy process may take a while.

Maybe you will never deal with a similar problem, but my idea is to put a real problem on the table in order to have a point of start and dive into real code so you can understand better the solution.

How the Example Solution Works

Using the traditional way we could, having the file list in the browser, start one copy request for each file.

We could show an animated GIF image next to the name of the file and change it to a green tick image once the request has been finished.

It is very unlikely that each of these processes last more than 30 seconds, but for our experiment we assume that they may last even more time.

Anyway, with this traditional way it is impossible to know how may percentage of the task is completed, so the animated GIF image has to be a generic one, showing only that there is some activity. For most of cases that is enough to give the user some feedback.

Lets see how this approach could look.

file list copy progress

It is necessary quite a bunch of JavaScript code to do things in the browser in order to: 1) show and update a pretty list of the processes, 2) start a new task when the previous finishes.

Keep in mind that this example is not perfect. For instance, the user may start the whole process again, so we must to disable the start button once started.

It may also be necessary to have some code to handle unexpected crashes. This is the simplest example to illustrate the concept I want to show you.

Known Limitations

As mentioned about, the HTTP request that is sent to start the server task is performed by the curl command. This is not the PHP Curl extensions. It is an executable command that must be installed with the Curl package. If the curl command is not available, this class will not work.

Another detail is that the curl command is started to run in the background redirecting its output to nowhere (/dev/null), so the command can continue to run even after our PHP start script exits.

The command line to start in background and redirect the output uses a syntax that only works on Linux/Unix shells. So this solution may not work for instance on Windows.

Trying to do More in Less Time Squeezing the Server

Lets say that we have a super server and we are not worried about the resources, but we are concerned about the time of execution of the long tasks in the server. If our client does not want to wait and queue the tasks, we can do all in parallel and finish earlier.  We will see how to do that in the next part of this article.

If you liked this article or have questions about this solution to start and monitor long server tasks, post a comment here.


You need to be a registered user or login to post a comment

1,349,537 PHP developers registered to the PHP Classes site.
Be One of Us!

Login Immediately with your account on:

FacebookGmail
HotmailStackOverflow
GitHubYahoo


Comments:

1. why executable curl, and what about security? - gonen radai (2015-09-29 06:01)
fsockopen can solve OS limitation, security needs to be handled... - 3 replies
Read the whole comment and replies




  Post a comment Post a comment   See comments See comments (4)   Trackbacks (0)  
  All package blogs All package blogs   Asynchronous Long Server Tasks Asynchronous Long Server Tasks   Blog Asynchronous Long Server Tasks package blog   RSS 1.0 feed RSS 2.0 feed   Blog Starting Long Server ...