[Kimchi-devel] [PATCH] [Wok 1/2] Issue #122 - Make AsyncTask stoppable.
Paulo Ricardo Paz Vital
pvital at linux.vnet.ibm.com
Wed Aug 31 17:22:26 UTC 2016
On Aug 31 01:51PM, Aline Manera wrote:
>
>
> On 08/30/2016 10:57 AM, pvital at linux.vnet.ibm.com wrote:
> > From: Paulo Vital <pvital at linux.vnet.ibm.com>
> >
> > This patch gives to user a way to 'stop' a Task that is still running by setting
> > the Task status to "killed".
> >
> > Since an AsyncTask is basic a thread running in the system and this thread can
> > execute a pure Python method or a background command (by using run_command()
> > from wok.utils), the developer must pass to AsyncTask constructor a method to be
> > executed by the DELETE operation, called here as 'kill_cb'. If none kill_cb is
> > passed, the task will not be able to stopped and an error message will be raised
> > to user if DELETE operation is executed. Otherwise, the kill_cb method will be
> > executed by kill() method (responsible to execute the DELETE operation) of
> > AsyncTask class and its status set to 'killed'.
> >
> > Signed-off-by: Paulo Vital <pvital at linux.vnet.ibm.com>
> > ---
> > docs/API/tasks.md | 2 ++
> > src/wok/asynctask.py | 18 +++++++++++++++++-
> > src/wok/i18n.py | 1 +
> > src/wok/model/tasks.py | 13 +++++++++++++
> > 4 files changed, 33 insertions(+), 1 deletion(-)
> >
> > diff --git a/docs/API/tasks.md b/docs/API/tasks.md
> > index e0c404f..2068f29 100644
> > --- a/docs/API/tasks.md
> > +++ b/docs/API/tasks.md
> > @@ -27,8 +27,10 @@ server.
> > * running: The task is running
> > * finished: The task has finished successfully
> > * failed: The task failed
> > + * killed: The task was killed by user
> > * message: Human-readable details about the Task status
> > * target_uri: Resource URI related to the Task
> > +* **DELETE**: Kill the Task, moving its status to 'killed'
> > * **POST**: *See Task Actions*
> >
> > **Actions (POST):**
> > diff --git a/src/wok/asynctask.py b/src/wok/asynctask.py
> > index b98ad9a..4a4ee32 100644
> > --- a/src/wok/asynctask.py
> > +++ b/src/wok/asynctask.py
> > @@ -26,6 +26,9 @@ import traceback
> > import uuid
> >
> >
> > +from wok.exception import OperationFailed
> > +
> > +
> > tasks_queue = {}
> >
> >
> > @@ -41,10 +44,11 @@ def clean_old_tasks():
> >
> >
> > class AsyncTask(object):
> > - def __init__(self, target_uri, fn, opaque=None):
> > + def __init__(self, target_uri, fn, opaque=None, kill_cb=None):
> > self.id = str(uuid.uuid1())
> > self.target_uri = target_uri
> > self.fn = fn
> > + self.kill_cb = kill_cb
> > self.status = 'running'
> > self.message = 'The request is being processing.'
> > self.timestamp = time.time()
> > @@ -79,3 +83,15 @@ class AsyncTask(object):
> > except KeyError:
> > msg = "There's no task_id %s in tasks_queue. Nothing changed."
> > cherrypy.log.error_log.error(msg % self.id)
> > +
> > + def kill(self):
> > + if self.kill_cb is None:
> > + msg = 'There is no callback to execute DELETE operation.'
> > + raise OperationFailed('WOKASYNC0002E', {'err': msg})
> > +
>
> It should be "InvalidOperation" exception.
OK!
/me never knows which exception is the best!!
>
> > + try:
> > + self.kill_cb()
> > + self.status = 'killed'
> > + self.message = 'Task killed by user.'
> > + except Exception, e:
> > + raise OperationFailed('WOKASYNC0002E', {'err': e.message})
>
> I see you are using WOKASYNC0002E with a placeholder for 'err' but in both
> cases the error message is manually set in the code.
>
> msg = 'There is no callback to execute DELETE operation.'
> self.message = 'Task killed by user.'
>
> I'd suggest to create 2 different error codes, one for each case above, so
> the entire message can be translated.
> Otherwise, the error message will keep in English and we can translate it to
> the language the user sets.
>
Here I'm raising the exception message. The self.message is the AsyncTask
message field and will not be used here.
I got your point, so I'll create one specific message to be used to
msg = 'There is no callback to execute DELETE operation.' and let
WOKASYNC0002E as is, because the idea is inform the exception error.
>
> > diff --git a/src/wok/i18n.py b/src/wok/i18n.py
> > index ade2ae9..937477f 100644
> > --- a/src/wok/i18n.py
> > +++ b/src/wok/i18n.py
> > @@ -34,6 +34,7 @@ messages = {
> > "WOKAPI0009E": _("You don't have permission to perform this operation."),
> >
> > "WOKASYNC0001E": _("Unable to find task id: %(id)s"),
> > + "WOKASYNC0002E": _("Unable to kill task due error: %(err)s"),
> > "WOKASYNC0003E": _("Timeout of %(seconds)s seconds expired while running task '%(task)s."),
> >
> > "WOKAUTH0001E": _("Authentication failed for user '%(username)s'. [Error code: %(code)s]"),
> > diff --git a/src/wok/model/tasks.py b/src/wok/model/tasks.py
> > index 6a2b4bf..8ae1ce4 100644
> > --- a/src/wok/model/tasks.py
> > +++ b/src/wok/model/tasks.py
> > @@ -68,3 +68,16 @@ class TaskModel(object):
> >
> > raise TimeoutExpired('WOKASYNC0003E', {'seconds': timeout,
> > 'task': task.target_uri})
> > +
> > + def delete(self, id):
> > + """
> > + 'Stops' an AsyncTask, by executing the kill callback provided by user
> > + when created the task. Task's status will be changed to 'killed'.
> > + """
> > + try:
> > + task = tasks_queue[id]
> > + except KeyError:
> > + raise NotFoundError("WOKASYNC0001E", {'id': id})
> > +
> > + if task.status is 'running':
> > + task.kill()
>
--
Paulo Ricardo Paz Vital
Linux Technology Center, IBM Systems
http://www.ibm.com/linux/ltc/
More information about the Kimchi-devel
mailing list