I'd like to execute a form submission asynchronously so the user gets a quick response. There appears to be no way of doing this in PHP. So I'm thinking about using the system() function to execute a php script as if it were executed from the command line using a nohup background(&) unix/linux technique. The problem is how do I get Drupal to work doing this? Can I just do what the cron.php script does?

Any pit falls?

Comments

Jaypan’s picture

Drupal's #ajax system allows for forms to be submitted asynchronously (if you set #ajax on the submit button).

donpwinston’s picture

The page is still going to wait until something is returned. I guess I should not have used the word "asynchronous".

If I was using Java I'd fire off a thread and then return. Can't do this in PHP.

Simpler is always better.

Jaypan’s picture

Can you please give more information regarding what it is you are trying to do? If you want to fire a background process, then the module WorldFallz recommended works well. Or maybe you can use a cron job. But without knowing your objective these are just stabs in the dark.

donpwinston’s picture

the particulars are immaterial. I just one to send back a page immediately after the user clicks the submit button without waiting for a couple of functions to finish executing.

Simpler is always better.

Jaypan’s picture

The more vague you are, the less specific we can be with a response.

Since you don't want to elaborate on the particulars, the only answer we can give is that you should do whatever it is you want to do as a background process. Good luck.

WorldFallz’s picture

I recently used https://drupal.org/project/background_process for a large submit function, and it works great.

donpwinston’s picture

There are no docs for this. Doesn't even have a readme file.

the project page has a couple of examples: $handle = blah.....

What the heck is $handle used for?

I submitted a module a year os so ago that does xsl transformations of xml in an input filter(d6) / text format(d7). I got a lot of grief for unimportant crap I did not do. How do these guys get away putting modules like this in the project area?

Simpler is always better.

Jaypan’s picture

Taking a look at this thread, WorldFallz and I both tried to help, and yet, nary a thank you in sight, but plenty of complaints.

I wish you luck your venture, but I'm done with this thread.

WorldFallz’s picture

im afraid i have to agree... the level of entitlement from some folks lately is really disheartening. oh well..... on to other threads....

donpwinston’s picture

Some commies these guys are.

For anyone else reading this "background_process" does not appear to recognize virtual hosts and gives you an error message when you install the module: "Could not determine default service host. Please configure background process in your settings.php".

There's no documentation that tells you how to do this.

By the way it doesn't take too much thought to figure out that

function mymodule_dosomething($x, $y) {
    sleep(999999999999999999999);
}

function mymodule_some_form_submit($form, $form_state) {
/*$handle =*/ background_process_start('mymodule_dosomething', $myvar1, $myvar2); 
//$handle is not necessary for 99/100 people using this. The example should omit it. It will just confuse people. 
}

is what I'm trying to do. Was it really necessary to explicitly type this? I've got other things to do.

good grief.

Simpler is always better.

Jaypan’s picture

Thank you for showing that I wasn't over-reacting with my previous comments.

WorldFallz’s picture

For the benefit of future users that stumble across this thread:

...does not appear to recognize virtual hosts...

Simply not true, I use it exclusively on virtual hosts and as I said above it does the job and works great. Not to mention also provides a report of currently in-progress background processes.

donpwinston’s picture

I have no confidence in the "background_process" module for obvious reasons.

I believe this will prove to be the superior method: (even though passing args to a cli php script is ugly)

$parm_str = escapeshellarg(serialize($fields));
system("nohup php mc_save_and_send.php $param_str 2>&1 &", $result);

mc_save_and_send.php (source)

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$fields = unserialize($argv[1]);
nc_mc_save_and_send($fields);

(Assuming the bootstrap.inc makes this work) I'll post my results in a few days. I'm worried that the cli php and the apache php are not the same thing.

Simpler is always better.

donpwinston’s picture

I got around to trying this recently and when executing a cli php script there are no $_SERVER data so the code in boostrap.inc will not work.

So I've got to think of something else. (Possibly wget and figure out some nice way of passing params)

Simpler is always better.

donpwinston’s picture

I create a menu/url/link with hook_menu with a callback function: (this happens to be Drupal 6)

$items['nc-multicase-save-and-send'] = array(
	'page callback' => 'nc_multicase_save_and_send_request',
	'access callback' => TRUE,
);
function nc_multicase_save_and_send_request() {
	$logger = new DrupalLogger();
	$fields = unserialize($_POST['data']);
	$logger->logFinest('nc_multicase_save_and_send_request', 'fields');
	$logger->logFinest('nc_multicase_save_and_send_request', $fields);
	drupal_set_header('Content-Type: text/plain');
	if (isset($fields['nc-key']) && $fields['nc-key'] == '1234') {
		nc_multicase_save_and_send($fields);
		print 1;
	}
	else
		print 0;
	return NULL;
}

And then I call the cli php script somewhere in my app where I don't want to wait for a long running operation as follows:

$param_str = escapeshellarg(serialize($fields));
system("nohup php multicase_save_and_send.php $param_str ".
  "> /dev/null 2> /dev/null & echo $!", $result);

The command line script(multicase_save_and_send.php) should be in the Drupal root directory and is as follows:

 //$Id$

$data = array('data' => $argv[1]);
$hostname = gethostname();

$ch = curl_init("http://$hostname/nc-multicase-save-and-send");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //Return data
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//Do not stop if invalid 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);	//Allow redirect
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch);
curl_close($ch);

exit(0);

I assume there is a windows version of nohup and background execution system commands. There may be problems on some servers executing the curl commands against the same server it is running on. So maybe this is not "ideal". Threads would be ideal. I found a pthread extension to php but it is considered "beta" and appears to require a rebuild of php.

Simpler is always better.