CodeIgniter RESTful, async / background process

2019-01-19 23:00发布

问题:

I'm using codeIgniter RESTful API (https://github.com/philsturgeon/codeigniter-restserver) that return information (json format) to my android/iphone app.

There are an operation where i send some values, if it is everything OK i return 200 code as response.

Now, i want to add a new operation at the same method: send notifications of this modifications with APNS (Apple Push Notificacion Service) and GCM (Google Cloud Messaging).

It works well when i have to send no more than 3-5 notifications, the problem is APNS, because i have to send this messages one by one and it takes a long time, so my apps recieves a timeout exception (all the notifications are sent but the user get the Error Connection...)

Can i send the 200 code response and then continue sending this notifications? (Something like this...)

function my_update_method_post(){
   //....GET my POST values
   update($data);
   $this->response(array('result'=>1),200));


   //Send Notifications
   ....
}

Thanks in advance...

回答1:

I found a solution that works perfect for me because i don't expect any result value. If notification can't be send...i log it in my database.

This is the function that i use to send "async" request (yes, This is not an asynchronous request, but it works how i'm looking for)

function curl_post_async($url, $params)
{
    $post_string = http_build_query($params);
    $parts=parse_url($url);

    $fp = fsockopen($parts['host'],
        isset($parts['port'])?$parts['port']:80,
        $errno, $errstr, 30);

    if(!$fp)
    {
        //Perform whatever logging you want to have happen b/c this call failed!    
    }
    $out = "POST ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['host']."\r\n";
    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out.= "Content-Length: ".strlen($post_string)."\r\n";
    $out.= "Connection: Close\r\n\r\n";
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);
}


回答2:

Yes this is possible.

You should look at PHP exec() and this link. You should set up a function in your controller to be called from the command line. you will then pass in an array of the GCM/APNS data to be used.

This solution is not ideal because you won't be able to tell the client that all message were sent successfully. You will send back 200 to say the request was received ok and that is all.



回答3:

Since PHP doesn't natively support threads or asynchronus function calls you will have to use a kindof hacky solution. Have a look at my question here: PHP file_get_contents() follow Content-length header

The Solution is to send a Connection: Close and Content-Length header, then make the client to be aware of these headers (see link above). In case of curl for example the connection will be closed as soon as the Content-Length is reached, but your PHP Script still runs "in the background" so you can start time consuming operations then.

Kind regards,

Stefan

P.S. If the Script takes really long to execute, make sure that the PHP max exection time doesn't get in your way



回答4:

Take a look at this article. I like this solution much more than one where you have the client tell the server to hang up immediately; there are multiple benefits if you build this solution on the server side.

  1. You know the server will continue processing once the client has disconnected
  2. The client can still receive a response from the server

EDIT

I'd not realized OP doesn't have access to the service here. In this case, the article I've mentioned is of little value. The problem here is the server is taking a long time to respond and hanging the client up. For this I suggest curl_multi_init. This allows you to make a number of requests simultaneously.