dont wait for script to finish - php

I have a php script that sends SMS, the problem is that it takes some time before every SMS is sent. In my site the page will wait until this script has finished running. How can I give user a message that SMS will be sent and resume the site's normal operation.

The only issue here is that the browser thinks it is are waiting for more output from the script when there will be none. You could offload to a seperate process, or use an asynchronous web call, or you could simply.....
<?php
register_shutdown_function('when_alls_done');
.... // render page
exit;
function when_alls_done()
{
if ($_REQUEST['send_to_phone']) {
send_sms($_REQUEST['send_to_phone'], $_REQUEST['message']);
}
}
The webserver should flush the request at the 'exit' and let the browser know that the response is complete (an explicit flush in the PHP code prior to that will either not flush the webserver buffer or it will result in the output being chunk encoded with another chunk to come).
C.

Put the messages in a queue in your database. Then have a script running as a cron job in the background to take care of the queue.

It's very easy when you know how:
<?php
echo 'A sms will be sent!';
fastcgi_finish_request();
// Put all your time consuming code here!
?>

Instead or sending the SMS right there and then you can store it somewhere (for example the database). You can then build an extra script (in PHP or whatever else you want) that polls the database looking for SMS to send and dispatches them. You can have this run every x seconds or minutes via cron or scheduled task according to your OS. This way you take a time consuming task out of the page whose job is to communicate with user in a timely manner.

If you are on LAMP
Write a cron job that will query a queue (in database) for pending SMS and send them.
In your script add the SMS to the queue.
Show the user status of his SMS on another page.
With Ajax you can query in background for the status of recently sent SMS. As soon as you see sent notify user.

to do this you can use ajax.
on some button press just send an ajax request to the php file moulded to send sms. and put a notification in the screen like 'sending sms!!!' and on the response of the ajax action change the 'sending sms' to 'success!!!'....
for using ajax you can use jquery..
if you dont know jquery comment me for the video tutorials... i have some beginners video tutorial for jquery....
Have a nice day!!!!!

Related

How do you make a long-running PHP script display a success message immediately?

The goal
I am trying to create a PHP script which emails a rather large (6MB) PDF file to users on a website that request it. A user enters their email address into a form, submits the form, and the file is sent to them via a PHP Mailer instance. The user is displayed a success page on submitting of the form.
The problem
After the data is submitted via the POST method, there is a long pause and the server eventually returns a 404. However, the email is received perfectly fine with the PDF attachment after a few minutes.
Troubleshooting / attempted solutions
I attribute the problem to PHP Mailer simply taking too long a time to send the email because of the large attachment. The server times out and resorts to returning a 404. In the mean time, the script eventually finishes processing and the email is thereafter received.
If I remove the attachment and just send a blank email, the script loads very quickly and shows the success/confirmation page.
I have considered creating a redirect, but everywhere that I have found explanations on how to achieve a redirect in PHP, it is said that you should kill the original script (which I do not want to do).
The question
How do I allow the email script to take its time to run, while immediately displaying a success message to the user so they are not left confused?
This is a task for a message queue. Store all information needed to send the mail in a queue and have a background task taking this information and sending your mails. If the insertion to the message queue succeeded, display the success message to the user.
If you do not have access to background scripts (e.g. shared hosting), you can still have a direct response. Just use ignore_user_abort(true) and send a correct Content-Length header. Browsers will trust that header and show the response, while your script can continue running and send the mail.
Another solution: Do a quick trick instead of attaching a big file in the email instantly. Give them the download link of the PDF File. Thus the content becomes too short. But no attachment.
You can effort to create unique URL to download the same PDF file by different users.
Otherwise, email queuing is good, as discussed.
Instead of emailing the file immediately, store the request in a database with all the details you need in order to send it. Then you can use a cronjob/scheduled task to regularly (every minute if you like) check the database for any outstanding requests and send the emails in the background.
As no codes were provided, you can use AJAX to call your script and show a success message wherever you want. The script will be called, the user will get the message and as soon the script finish, the user will receive the email.
Of course, the success message shouldn't be implemented in the AJAX handlers, otherwise the message will be delayed as well.
This is a good use case for an asynchronous job queue such as Gearman or Beanstalk.
You have to run an external worker process that will wait for tasks from the job server.
On the web server side, just create the task, send it to the job server to dispatch it to the worker process, and exit the PHP script.
The worker process will then proceed to send the mails while the web server can continue serving HTTP requests.

PHP script in background without user waiting

I have a webform that sends data to PHP script.
PHP script may take a while to process the data. What I want to do is to send raw data to database, then redirect the visitor to "thank you" page and then continue processing the data in background. Important thing is that the script must continue working even if the visitor closes "thank you" page.
Can you advise which solution should I look into?
P.S. I use nginx + php-fpm if that matters.
UPDATE. I've found info about using ignore_user_abort(true). Could this be the way to go?
What I want to do is to send raw data to database, then redirect the visitor to "thank you" page and then continue processing the data in background.
That basically describes how I'd do it right there, actually.
Consider two separate applications. One is the web application, which saves the user input to the database and then continues to interact with the user. The other is a scheduled console application (a standalone script invoked by cron most likely) which looks for data in the database to be processed and processes it.
The user uploads the data, receives a "thank you" message, and his/her interaction is complete. The next time the scheduled task runs (every couple minutes, maybe?) it sees the pending data in the database, flags it as being processed (so if another instance of the script runs it doesn't also try to process the same data), processes it, flags it as being done (so it doesn't pick it up again next time), and completes.
You can notify the user of the completed process a couple of different ways. The back-end script can send the user an email (active notification), or perhaps the web application can examine the table for the flagged completed records the next time the user visits the page (passive notification).
Something like this should work :
pclose(popen('php script.php &', 'r'));
http://fr2.php.net/manual/fr/function.popen.php
You can also use more options or others functions to get more control over the execution :
http://fr2.php.net/manual/fr/function.proc-open.php
But use this carefully and be sure you need this way to resolve your problem.
Ajax would be nice.
You need to do the thing asynchronously. Use AJAX to achieve this

php running separately avoiding time out for user

I would like to find a way to have my user not having to wait for the output of a php script and being redirected to a page while the script is running on the server.
Basically the user submits a form which takes quite long to process and I would like to redirect the user to a page notifying him that the form is being processed and that its output will be later available (I thought about opening a tab when the output is ready).
Basically I would like something like this, which I tried without success, the
if ($form_valid) {
process_form(); // this would need not to be running on the current page so that the user don't have to wait for it to be ready (timeout problems)
header('Location: http://example.com/form_submitted_output_coming_soon.html');
}
I hope that it is not too vague.
Thank you in advance for any help / advice on how I could do that.
It really depends on the time the script takes to execute if it's seconds, under 10 I would do an ajax request and have a modal progress message
If they take extended amounts of time my approach would be to create or use an existing task scheduler/ report generator
a single system scheduled task entry calling a central management script ( probably not optimal )
You mark a task/report for execution
Concurrency. Count, limit the number currently executing ( so you don't over load the server)
users pool via ajax for their tasks / reports or push to the clients with web sockets
Example on how to fork php to background
Update
I think you would get better performance out of a bot continuously check a database or file for work to do and submitting results back to the database. Alerting users via ajax, web sockets and or email when the work that they need is done / updated.
Here is a good introduction on how to build a web crawler in php
The best approach for solving this kind of problem is to use AJAX to make the request to the server in the background and then update the user once it has finished processing.
You may submit the form with an asynchronous request (ajax) and handle the page forward also with javascript. This way your form is handled asynchronously - you may even wait for the response to tell the user once you have an answer. This asynchronous request will not block the UI.
Just for completeness if you really really want to use php only for this:
Run PHP Task Asynchronously

Terminate connection to jQuery AJAX request, keep processing php on server side?

I have a signup form that calls a PHP script which can interact with our CRM's API, like so:
CRM API <--> PHP script <--> Signup form
The signup form passes some information to the PHP script in one
AJAX call
The PHP script run a dozen API calls to the CRM to create
an account and attach various data
The CRM returns the new account id it just created to the PHP script
The PHP script passes the account id back to the signup form, at which point the AJAX call is complete and the signup form can continue.
The problem is #2, those dozen calls take about 20 seconds to complete, but the data the signup form needs is generated after the first API call so it could in theory return that data much sooner and do the rest of the stuff server side without holding that AJAX call open the whole time.
I tried flush() and ob_flush() which does output account id to the client before processing is complete, but the jQuery AJAX connection remains open so I'm still stuck waiting for the connection to be closed on the signup form side before anything happens.
So what's the easiest route for returning that account id to the form as fast as possible?
Maybe break out using curl and exec?
if(signing up){
stuff
exec(curl myself, notsignup)
}
else {
bunch of api calls
}
You should probably think about creating a seperate process for the rest of the steps that are needed. One way is that you could after the #1 first api calls has been completed. It responds back to the user, and doesn't try to complete the rest of the 20 calls on the user side.
Then create a queue that will finish the rest. You could always create a table in mysql to store the queue.
Next just create a cronjob that will run in the background, knocking the queue out.
Note: You will not want this cronjob to just start and never stop. Maybe have it run every 5 minutes, but before it starts to run, check to see if another cron is still in progress. If it is then it will check in another 5 minutes to see if it is ok to run.
Hope this helps!
If you only need the information from the first API call to return the form, then I would probably try a different workflow:
Form calls PHP Script
PHP Calls first API Call
PHP Returns to Form
Form processes response
Form calls second PHP Script to complete the process
PHP finishes API Calls (the form can abandon at this point since it sounds like you don't care what happens from here on out).
The workflow requires a little more work and co-ordination for the developer, but presents the most responsive interface to the user.

Using CodeIgniter and PHP, is there a way to issue a redirect to the client and continue executing the present script?

I have a page which handles form input. It does a few things, sends a few emails, and redirects the client to another page. Things work well.
The issue I that sending email is slow, and if I have to send a couple emails, the response time is unacceptable. I would like to redirect the client to the result page, and then send the emails. Unfortunately, the redirect() call in CodeIgniter ends execution.
Is there a way to do a 302 redirect and allow the execution of the script to continue?
It is important that the 302 redirect headers get flushed out. It would be OK, but is not required, that the connection be closed. What is important that the user gets redirected before the emails get sent, in order to not have to wait for the email sending to finish.
I think using a message queue would be more appropriate than having a possible zombie process sitting there. Essentially when this action is taken dump a job into a job queue with the body of the e-mail, who it's going to, the subject etc. Then have a cron job set up to read this queue every two minutes, say, and send out the e-mail.
You can also look into using something like the Simple Queue Service from Amazon (http://aws.amazon.com/sqs/faqs/#What_can_I_do_with_Amazon_SQS) along with the Simple E-Mail Service to create a scaleable solution.

Categories