wp-background-processing icon indicating copy to clipboard operation
wp-background-processing copied to clipboard

function handle() not firing

Open kevinnivek opened this issue 8 years ago • 12 comments

Hello!

Not sure if I'm missing something. I'm adding an item for an async request :

$example->example_request = new WP_Example_Request();
$example->example_request->data( array( 'value1' => 'the value 1', 'value2' => 'the value 2' ) );
$example->example_request->dispatch();

Then my class extension looks like this :

class WP_Example_Request extends WP_Async_Request {

    /**
     * @var string
     */
    protected $action = 'example_request';

    /**
     * Handle
     *
     * Override this method to perform any actions required
     * during the async request.
     */
    protected function handle() {
        error_log('test handle');
        // Actions to perform
    }

}

Not seeing "test handle" in the logs at all. So handle() is not firing at all. Any idea why? I must be missing something.

kevinnivek avatar Sep 20 '16 19:09 kevinnivek

I'm experiencing a similar issue only that it's working fine on one server and not at all on another.

I'm getting the following response from handle() when logging it:

array (
'headers' =>
array (
),
'body' => '',
'response' =>
array (
'code' => false,
'message' => false,
),
'cookies' =>
array (
),
'http_response' => NULL,
)

NiklasHogefjord avatar Oct 07 '16 07:10 NiklasHogefjord

Hi. I thought I had this problem as well using either Async or Background processing, but I tried running my background process anyway and it was producing the expected output file, but error_log was not outputting to the normal log file as defined in my nginx config. I used the php_ini_loaded_file() function to save the ini file path to the WordPress DB using update_user_option(). If I edit that ini file (in my case it was /etc/php5/fpm/php.ini) and set the error_log directive (i.e. error_log = syslog), then I could see the messages I was logging in /var/log/syslog. I am not sure if this is just because of how wp_remote_post() works, or just the way nginx/PHP-FPM work.

Semi-related -- another way I was testing initially was to use the sleep() function, but this seems to block the script, so it appeared that things weren't working correctly there as well. You can save yourself a lot of time by making sure you have PHP logging configured correctly and using a realistic function/process, rather than using sleep(), exec(), or any other blocking function for testing.

whirled avatar Oct 19 '16 16:10 whirled

Thought I was doing something wrong... But it seemed Wordpress was logging to PHP error log, outside of Wordpress dir. Not what I expected.

So I changed

error_log($message);

to:

file_put_contents(WP_PLUGIN_DIR . '/my_plugin/logs/my.log', '['.date(DATE_RFC2822).'] '.$message.PHP_EOL , FILE_APPEND | LOCK_EX);

Now I got the result I wanted.

StylizeR avatar Dec 03 '16 20:12 StylizeR

This may be related to the problem mentioned by @NiklasHogefjord. It's pretty obvious in hindsight, but easily overlooked. The server hosting the site needs to be able to resolve the hostname of your site. This plugin uses wp_remote_post().

I had setup a site on a linux server, and created a HOSTS entry on my development workstation, but not on the server. It took a bit to figure out that things were not working because wp_remote_post() was not able to connect to the site by hostname.

whirled avatar Dec 03 '16 20:12 whirled

Same issue here. Not working at all.

pyksid avatar Feb 13 '17 17:02 pyksid

Maybe mine is a little different, but my handle in single processing does not fire everytime. I did a count check and it only fires every other time or not at all for 3-5 dispatches... I hope that made sense? lol

kinged007 avatar Mar 07 '17 12:03 kinged007

I was also having the same problem but the problem was that I was initializing the WP_Async_Request on the wrong place. This class initializes the ajax actions, so it needs to be on the right place.

I added my solution here: #35

dbeja avatar Apr 10 '17 11:04 dbeja

@kevinnivek Not sure if this helps in your situation (it doesn't in mine), but I noticed something when looking at your code. According to documentation the last line should look like $example->example_request->save()->dispatch(); ... Looks like in your above logic the save() method was omitted. Maybe it helps!

dskvr avatar Apr 12 '17 08:04 dskvr

Ok, I just spent a day and a half debugging this same issue and finally got it working.

Like @NiklasHogefjord, my code was working fine on other servers except my beloved WP Engine site. To throw more confusion into the mix, it was only happening intermittently. Sometimes the batches would all finish sans errors, but sometimes they would just halt and seemingly timeout.

While debugging, I found that the batch itself was indeed being saved to the options table. This meant that the save() function was working properly. I eventually traced the problem to the wp_remote_post() function within the dispatch() method of the parent Async class.

I tried logging the results of wp_remote_post() but always received an empty array (even for successful batches) that looked exactly liked:

array (
'headers' =>
array (
),
'body' => '',
'response' =>
array (
'code' => false,
'message' => false,
),
'cookies' =>
array (
),
'http_response' => NULL,
)

To get an actual response from wp_remote_post(), I had to remove the blocking argument from the get_post_args() method of the parent Async class. Whether this should be removed permanently is unclear to me, but it did finally give me a response to work with. Now I was able to actually see that I was getting a cURL error for those batches that were not working.

The specific error was: "cURL error 28: Operation timed out after 1000 milliseconds with 0 bytes received". I spent another 3-5 hours trying to figure this out. I eventually traced the issue to the timeout argument located within the same get_post_args() method as above. The default value here is 0.01, which I instead set to 5 seconds.

The timeout property here is interesting. According to the Codex it sets "the time in seconds, before the connection is dropped and an error is returned". https://codex.wordpress.org/HTTP_API#Other_Arguments So in other words, for whatever reason, the wp_ajax post to handle the batch process was being dropped immediately for certain batches, and giving it a bit more time to wait seems to have fixed the issue for me.

@A5hleyRich can you elaborate on why setting the timeout to a low value like 0.01 is needed? I don't seem to be encountering any performance degradations now either. Then again, in my case I have 7 different classes which all instantiate their own instances of the WP_Background_Process so perhaps that's why?

Anyway, hope this helps someone!

arobbins avatar Aug 13 '18 05:08 arobbins

Thank you dbeja, you saved me! Hope I don't run into other issues as cited in this thread when I port my project to another server. Thanks to everyone who is posting here.

karlazz avatar Nov 06 '18 21:11 karlazz

Thanks @arobbins! you saved my day. I spent hours on this issue, wasn't clear why I was receiving always an empty array. Now I was able to get the real issue (Domain name not found in my case).

Anyway having blocking false and timeout supershort will provide higher performance, for example if the request to the server itself take too long for some reason, having timeout almost zero let the request immediately return but it isn't canceled (so the async action is performed).

Splact avatar Mar 15 '19 15:03 Splact

There's subtle limitation of the package. It useswp_ajax_... action to trigger your handle function. The problem is due to the order that the actions got triggered. I believe in your code where you created the WP_Example_Request, it's already too late and already past the time for triggering wp_ajax_... action. Therefore, your handle function never gets a chance to run. I came to the same problem trying to create the async request inside rest_api_init action.

correct usage

create the request instance in action init or plugins_loaded (anything executed before wp_ajax... is fine) then use the request instance anywhere you desire.

JJPro avatar Apr 21 '20 20:04 JJPro

It might be something to do with the server not being able to reach your domain?

On your Ubuntu server, check your /etc/hosts file:

e.g.

127.0.0.1 somehostname localhost yourdomain.com www.yourdoamin.com

psydigital avatar Apr 06 '23 12:04 psydigital

Closing ancient issue. :smile: (but in general we see this kind of issue if the server does not know itself by the domain of the site or security software is dropping local requests without responding)

ianmjones avatar Apr 11 '23 19:04 ianmjones