NAME
Padre::Role::Task - A role for objects that commission tasks
DESCRIPTION
This is a role that should be inherited from by objects in Padre's permanent model that want to commision tasks to be run and have the results fed back to them, if the answer is still relevant.
Task Revisions
Objects in Padre that commission tasks to run in the background can continue processing and changing state during the queue'ing and/or execution of their background tasks.
If the object state changes in such a way as to make the results of a background task irrelevant, a mechanism is needed to ensure these background tasks are aborted where possible, or their results thrown away when not.
Padre::Role::Task provides the concept of "task revisions" to support this functionality.
A task revision is an incrementing number for each owner that remains the same as long as the results from any arbitrary launched task remains relevant for the current state of the object.
When an object transitions a state boundary it will increment it's revision, whether there are any running tasks or not.
When a task has completed the task manager will look up the owner (if it has one) and check to see if the current revision of the owner object is the same as when the task was scheduled. If so the Task Manager will call the on_finish
handler passing it the task. If not, the completed task will be silently discarded.
Sending messages to your tasks
The Padre::Task API supports bidirection communication between tasks and their owners.
However, when you commission a task via task_request
the task object is not returned, leaving you without access to the task and thus without a method by which to send messages to the child.
This is intentional, as there is no guarentee that your task will be launched immediately and so sending messages immediately may be unsafe. The task may need to be delayed until a new background worker can be spawned, or for longer if the maximum background worker limit has been reached.
The solution is provided by the on_message
handler, which is passed the parent task object as its first parameter.
Tasks which expect to be sent messages from their owner should send the owner a greeting message as soon as they have started. Not only does this let the parent know that work has commenced on their task, but it provides the task object to the owner once there is certainty that any parent messages can be dispatched to the child successfully.
In the following example, we assume a long running "service" style task that will need to be interacted with over time.
sub service_start {
my $self = shift;
$self->task_reset;
$self->task_request(
task => 'My::Service',
on_message => 'my_message',
on_finish => 'my_finish',
);
}
sub my_message {
my $self = shift;
my $task = shift;
# In this example our task sends an empty message to indicate "started"
unless ( @_ ) {
$self->{my_service} = $task;
return;
}
# Handle other messages...
}
METHODS
task_owner
Padre::Role::Task->task_owner( 1234 );
The task_owner
static method is a convenience method which takes an owner id and will look up the owner object.
Returns the object if it still exists and has not changed it's task revision.
Returns undef
of the owner object no longer exists, or has changed its task revision since the original owner id was issued.
task_manager
The task_manager
method is a convenience for quick access to the Padre's Padre::TaskManager instance.
task_revision
The task_revision
accessor returns the current task revision for an object.
task_reset
The task_reset
method is called when the state of an owner object significantly changes, and outstanding tasks should be deleted or ignored.
It will change the task revision of the owner and request the task manager to send a standard cancel
message to any currently executing background tasks, allowing them to terminate elegantly (if they handle
task_request
$self->task_request(
task => 'Padre::Task::SomeTask',
on_message => 'message_handler_method',
on_finish => 'finish_handler_method',
my_param1 => 123,
my_param2 => 'abc',
);
The task_request
method is used to spawn a new background task for the owner, loading the class and registering for callback messages in the process.
The task
parameter indicates the class of the task to be executed, which must inherit from Padre::Task. The class itself will be automatically loaded if required.
The optional on_message
parameter should be the name of a method (which must exist if provided) that will receive owner-targetted messages from the background process.
The method will be passed the task object (as it exists after the prepare
phase in the parent thread) as its first parameter, followed by any values passed by the background task.
If no on_message
parameter is provided the default method null task_message
will be called.
The optional on_finish
parameter should be the name of a method (which must exist if provided) that will receive the task object back from the background worker once the task has completed, complete with any state saved in the task during its background execution.
It is passed a single parameter, which is the Padre::Task object.
If no on_finish
parameter is provided the default method null task_finish
will be called.
Any other parameters are passed through the constructor method of the task.
task_finish
The task_finish
method is the default handler method for completed tasks, and will be called for any task_request
where no specific on_finish
handler was provided.
If your object issues only one task, or if you would prefer a single common finish handler for all your different tasks, you should override this method instead of explicitly defining an on_finish
handler for every task.
The default implementation ensures that every task has an appropriate finish handler by throwing an exception with a message indicating the owner and task class for which no finish handler could be found.
task_message
The task_message
method is the default handler method for completed tasks, and will be called for any task_request
where no specific on_message
handler was provided.
If your object issues only one task, or if you would prefer a single common message handler for all your different tasks, you should override this method instead of explicitly defining an on_finish
handler for every task.
If none of your tasks will send messages back to their owner, you do not need to define this method.
The default implementation ensures that every task has an appropriate finish handler by throwing an exception with a message indicating the owner and task class for which no finish handler could be found.
COPYRIGHT & LICENSE
Copyright 2008-2012 The Padre development team as listed in Padre.pm.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
The full text of the license can be found in the LICENSE file included with this module.