Background task not working?

Background task not working?

by muzaki azami -
Number of replies: 10
I'm trying to create a background task to send a saved file when an activity is created, to avoid timeout issue when the file being sent is too heavy.

So far, I've tried to mimick what mod_forum has done, I created a directory under class folder of my module for task classes: 'MYPLUGIN/classes/task'

With one class, 'send_to_ws', looking like this:

namespace mod_MYPLUGIN\task;

defined('MOODLE_INTERNAL') || die();
class send_to_ws extends \core\task\adhoc_task {
    public function execute() {
        $data = $this->get_custom_data();
        $payload = json_encode(array("data"=> $data['info']));
        $ch->post('http://127.0.0.1:8001/', array('info'=>$payload, 'file'=> $data['file']));
    }
}

And it will be called during the add_instance function execution like this:

$sendfile = new mod_MYPLUGIN\task\send_to_ws();
        $sendfile->set_custom_data(array(
            'info' => $info,
            'file' => $file,
        ));
        \core\task\manager::queue_adhoc_task($sendfile);
However, the task doesn't seem to be executed. My webservice doesn't receive any curls, and when I checked the task logs (in DashboardSite administration > ServerTasks > Task logs) and running tasks (in Dashboard > Site administration > Server > Tasks > Tasks running now), they're empty. And for the record, I've enabled cron.

I don't know where did I go wrong. Help is very much appreciated.



Average of ratings: -
In reply to muzaki azami

Re: Background task not working?

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Looking at your code, you have an undefined variable called $ch - calling 'post' on it won't do anything.

Did you mean to do something like:

$ch = new curl();
$ch->post('http://127.0.0.1:8001/', array('info'=>$payload, 'file'=> $data['file']));

?
In reply to Davo Smith

Re: Background task not working?

by muzaki azami -
Oops didn't notice that the message formatting deleted the "new curl()" line my bad

Yes, I did create it:

Here's the full thing (without trying to format it):

class send_to_ws extends \core\task\adhoc_task {
public function execute() {
$data = $this->get_custom_data();

$ch = new curl;
$payload = json_encode(array("data"=> $data['info']));
$ch->post('http://127.0.0.1:8001/', array('info'=>$payload, 'file'=> $data['file']));
}
}
In reply to muzaki azami

Re: Background task not working?

by Andreas Grabs -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers Picture of Translators

Hi,

did you register your task in db/tasks.php? After that you have to increase the version of your plugin.

Best regards
Andreas

In reply to Andreas Grabs

Re: Background task not working?

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Andreas - it's an ad-hoc task, not a scheduled task, so it shouldn't appear in tasks.php.

Muzaki - have you tried calling the code directly to see if it works when not in an ad-hoc task? I'd also advise setting up xdebug with your IDE, then you can stick a breakpoint in your code and step through to see what happens.

One more thought - when you add data to an ad-hoc task, the data is converted into a JSON string and stored in the database. Any class instances will be lost - you'll need to re-instantiate the class objects from the data you included. Could that be the issue?
In reply to Davo Smith

Re: Background task not working?

by muzaki azami -

>have you tried calling the code directly to see if it works when not in an ad-hoc task?

I have. And it worked perfectly fine. 

I am using xdebug, and placed a breakpoint on the task class, but it never triggers, strangely enough


>when you add data to an ad-hoc task, the data is converted

Oh I see... Well, for the most part, the post data is mostly JSON to begin with. Although for the files, do I have to get the file again from file storage?


In reply to muzaki azami

Re: Background task not working?

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
The easiest way would probably be to store the pathnamehash of the file when setting up the ad-hoc task ($file->get_pathnamehash()) and store this in the ad-hoc task data.

When the ad-hoc task runs, call:

$fs = get_file_storage();
$file = $fs->get_file_by_hash($data['pathnamehash']);

(assuming you called it 'pathnamehash' when you stored it in the ad-hoc task data) - that way you will have a stored_file instance to pass on to the curl instance. Make sure you double-check that $file is not false - the file _might_ have been deleted before the ad-hoc task runs ...
Average of ratings: Useful (1)
In reply to Davo Smith

Re: Background task not working?

by muzaki azami -
I see what you're talking about now in regards to data getting converted, I keep getting this error: "Adhoc task failed: mod_MYPLUGIN\task\send_to_ws,Cannot use object of type stdClass as array"

Even though I ensured that I pass an array:
$info_array = array(
'name' => $MYPLUGIN->name,
'videotype' => $MYPLUGIN->videotype,
'language' => $MYPLUGIN->language,
'personagender' => $MYPLUGIN->personagender,
'lecturemajor' => $MYPLUGIN->lecturemajor,
);

$fhash = $file->get_pathnamehash();

$sendfile = new mod_MYPLUGIN\task\send_to_ws();
$sendfile->set_custom_data(array(
'info' => $info_array,
'filehash' => $fhash,
));
\core\task\manager::queue_adhoc_task($sendfile);
In reply to muzaki azami

Re: Background task not working?

by Renaat Debleu -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers

Adhoc tasks are difficult to debug, perhaps the code dies in the middle of the script.

Even tasks that pass PHPUnit tests, can fail in real life. But it can be a good idea to have this test to detect basic errors:

        $task = new \mod_MYPLUGIN\send_to_ws();
        $task->set_blocking(true);
        $task->set_custom_data(['info' => $info, 'file' => $file]);
        \core\task\manager::queue_adhoc_task($task);
        \phpunit_util::run_all_adhoc_tasks();

But the adhoc environment is different from the PHPUnit environment. there is no current user, globals as $OUTPUT and $PAGE are unavailable, and also namespacing can be tricky. I would start with these changes:

        $curl = new \curl();
        $payload = \json_encode(["data"=> $data['info']]);

 

Average of ratings: Useful (2)
In reply to muzaki azami

Re: Background task not working?

by muzaki azami -
After checking out admin/cron.php I digged this:

Execute adhoc task: mod_MYPLUGIN\task\send_to_ws
... started 08:26:37. Current memory use 54.6MB.
... used 0 dbqueries
... used 0.00034403800964355 seconds
Adhoc task failed: mod_MYPLUGIN\task\send_to_ws,Class 'mod_MYPLUGIN\task\curl' not found
Backtrace:
* line 341 of \lib\cronlib.php: call to mod_MYPLUGIN\task\send_to_ws->execute()
* line 198 of \lib\cronlib.php: call to cron_run_inner_adhoc_task()
* line 76 of \lib\cronlib.php: call to cron_run_adhoc_tasks()
* line 81 of \admin\cron.php: call to cron_run()

I am quite confused...
In reply to muzaki azami

Re: Background task not working?

by muzaki azami -
Nevermind, solved! Thanks to Renaat suggestion of putting '\'