Example #1
0
    def _check_expired_tasks(self):
        time_now = int(now())
        if time_now - self._ttl_check_last_run < 1000:  # 1000 = 1sec
            return
        self._ttl_check_last_run = time_now

        TTL = SETTINGS.WORKER_TASK_TIMEOUT * 1000
        for scheduled_task_name, scheduled_task_history in self.scheduler_tasks_history.items():
            scheduled_task = self.scheduler_tasks.get(scheduled_task_name)
            if (scheduled_task_history.get('next_run')
              and scheduled_task_history.get('scheduled_task_id')
              and (time_now - scheduled_task_history.get('next_run')) > (scheduled_task.get('ttl') or SETTINGS.WORKER_TASK_TIMEOUT)*1000):
                task_id = scheduled_task_history.get('scheduled_task_id')
                log.info('Fix broken task id={}, name={}'.format(task_id, scheduled_task_name))
                # Get task object from redis key
                key = SETTINGS.TASK_STORAGE_KEY.format(scheduled_task_history.get('scheduled_task_id')).encode('utf-8')
                task_obj = yield from self.connection.get(key)
                # Deserialize task object
                try:
                    if not task_obj:
                        raise TypeError()
                    task = Task.deserialize(task_obj)
                    if task.status != Task.SUCCESSFUL:
                        # Update task object status
                        task = task._replace(status=Task.FAILED)
                        # Set new status to redis
                        yield from self.connection.set(key, task.serialize(), expire=SETTINGS.TASK_STORAGE_EXPIRE)
                except TypeError as ex:
                    task = None
                    log.error("Wrong task id={}".format(scheduled_task_history.get('scheduled_task_id')), exc_info=True)
                    yield from self.connection.delete([key])

                # Publish message about finish (FAILED)
                if task:
                    yield from self.connection.publish(SETTINGS.TASK_CHANNEL.format(task_id).encode('utf-8'), task.status.encode('utf-8'))
                else:
                    yield from self.connection.publish(SETTINGS.TASK_CHANNEL.format(task_id).encode('utf-8'), Task.FAILED.encode('utf-8'))

                # Update scheduler information
                # Store next_run in scheduled
                try:
                    task_scheduler_obj = yield from self.connection.hget(SETTINGS.SCHEDULER_HISTORY_HASH, scheduled_task_name.encode('utf-8'))
                    task_scheduler = SchedulerTaskHistory.deserialize(task_scheduler_obj)
                    if task and task.status == Task.SUCCESSFUL:
                        scheduled_task_history['last_run'] = scheduled_task_history.get('next_run', 0)
                        scheduled_task_history['next_run'] = 0
                        task_scheduler = task_scheduler._replace(last_run=task_scheduler.next_run, next_run=0, scheduled_task_id=None)
                    else:
                        scheduled_task_history['next_run'] = 0
                        scheduled_task_history['scheduled_task_id'] = None
                        task_scheduler = task_scheduler._replace(next_run=0, scheduled_task_id=None)
                    yield from self.connection.hset(SETTINGS.SCHEDULER_HISTORY_HASH, task_scheduler.name.encode('utf-8'), task_scheduler.serialize())
                except:
                    # We lost SCHEDULER_HISTORY_HASH in db
                    if task and task.status == Task.SUCCESSFUL:
                        scheduled_task_history['last_run'] = scheduled_task_history.get('next_run', 0)
                        scheduled_task_history['next_run'] = 0
                    else:
                        scheduled_task_history['next_run'] = 0
                        scheduled_task_history['scheduled_task_id'] = None
Example #2
0
 def create_task(self, name, task_type, run_at, ttl, kwargs, store_to):
     task_id = hashlib.md5(
         ujson.dumps([
             codecs.encode(os.urandom(16), 'hex_codec'), name, task_type,
             run_at, ttl, kwargs, store_to
         ]).encode('utf-8')).hexdigest()
     if store_to == Task.STORE_TO_KEY:
         store_to = 'STORE_TO_KEY:' + SETTINGS.TASK_RESULTS_STORAGE_KEY.format(
             task_id)
     task = Task(id=task_id,
                 name=name,
                 type=task_type,
                 kwargs=kwargs,
                 run_at=run_at,
                 ttl=ttl,
                 status=Task.SCHEDULED,
                 store_to=store_to)
     return task
Example #3
0
 def _deserialize_task(self, raw_task):
     try:
         task_obj = yield from self.connection.get(SETTINGS.TASK_STORAGE_KEY.format(raw_task.decode('utf-8')).encode('utf-8'))
         if not task_obj:
             raise TypeError()
         task = Task.deserialize(task_obj)
         log.info("Got new task id={}, type={}, status={}".format(task.id, task.type, task.status))
         if not task.status == Task.SCHEDULED:
             log.error("Wrong status={} for task id={}, type={}; Should be SCHEDULED".format(task.status, task.id, task.type))
             return
         return task
     except TypeError as ex:
         log.error("Wrong task_id {}".format(raw_task))
         return
     except (pickle.UnpicklingError, EOFError, TypeError, ImportError):
         yield from self.connection.lrem(SETTINGS.INPROGRESS_QUEUE, value=raw_task)
         log.error("Wrong message in queue", exc_info=True)
         return
Example #4
0
def handle_task_post():
    # TODO: needs to check for existence in request
    # TODO: needs to check for uniqueness in name (for this user)
    task = Task()
    task.name = request.form['name']
    task.workflow = request.form['workflow']
    task.metadata = request.form['extra_info']
    nodes = Node.query(Node.workflow == task.workflow,
                       Node.parent_node == None).fetch(100)
    if len(nodes) < 1:
        flash("No valid root nodes found for this workflow." +
              " Are you sure this workflow exists?")
        return "error"
    if len(nodes) > 1:
        flash("More than one root node exists for this workflow." +
              " Something has gone terribly wrong somewhere...")
        return "error"
    root_node = nodes[0]
    task.active_nodes.append(root_node)
    # TODO: figure out what the return value is here and check it
    task.put()
    return "success"
Example #5
0
 def _deserialize_task(self, raw_task):
     try:
         task_obj = yield from self.connection.get(
             SETTINGS.TASK_STORAGE_KEY.format(
                 raw_task.decode('utf-8')).encode('utf-8'))
         if not task_obj:
             raise TypeError()
         task = Task.deserialize(task_obj)
         log.info("Got new task id={}, type={}, status={}".format(
             task.id, task.type, task.status))
         if not task.status == Task.SCHEDULED:
             log.error(
                 "Wrong status={} for task id={}, type={}; Should be SCHEDULED"
                 .format(task.status, task.id, task.type))
             return
         return task
     except TypeError as ex:
         log.error("Wrong task_id {}".format(raw_task))
         return
     except (pickle.UnpicklingError, EOFError, TypeError, ImportError):
         yield from self.connection.lrem(SETTINGS.INPROGRESS_QUEUE,
                                         value=raw_task)
         log.error("Wrong message in queue", exc_info=True)
         return
Example #6
0
def handle_task_post():
    # TODO: needs to check for existence in request
    # TODO: needs to check for uniqueness in name (for this user)
    task = Task()
    task.name = request.form['name']
    task.workflow = request.form['workflow']
    task.metadata = request.form['extra_info']
    nodes = Node.query(Node.workflow == task.workflow,
                       Node.parent_node == None).fetch(100)
    if len(nodes) < 1:
        flash("No valid root nodes found for this workflow."
              + " Are you sure this workflow exists?")
        return "error"
    if len(nodes) > 1:
        flash("More than one root node exists for this workflow."
              + " Something has gone terribly wrong somewhere...")
        return "error"
    root_node = nodes[0]
    task.active_nodes.append(root_node)
    # TODO: figure out what the return value is here and check it
    task.put()
    return "success"
Example #7
0
def handle_tasks_json():
    return json.dumps([task.to_json() for task in Task.query().fetch(100)])
Example #8
0
def handle_tasks():
    tasks = Task.query().fetch(100)
    return render_template("tasks.html", tasks=tasks)
Example #9
0
    def _check_expired_tasks(self):
        time_now = int(now())
        if time_now - self._ttl_check_last_run < 1000:  # 1000 = 1sec
            return
        self._ttl_check_last_run = time_now

        TTL = SETTINGS.WORKER_TASK_TIMEOUT * 1000
        for scheduled_task_name, scheduled_task_history in self.scheduler_tasks_history.items(
        ):
            scheduled_task = self.scheduler_tasks.get(scheduled_task_name)
            if (scheduled_task_history.get('next_run')
                    and scheduled_task_history.get('scheduled_task_id')
                    and (time_now - scheduled_task_history.get('next_run')) >
                (scheduled_task.get('ttl') or SETTINGS.WORKER_TASK_TIMEOUT) *
                    1000):
                task_id = scheduled_task_history.get('scheduled_task_id')
                log.info('Fix broken task id={}, name={}'.format(
                    task_id, scheduled_task_name))
                # Get task object from redis key
                key = SETTINGS.TASK_STORAGE_KEY.format(
                    scheduled_task_history.get('scheduled_task_id')).encode(
                        'utf-8')
                task_obj = yield from self.connection.get(key)
                # Deserialize task object
                try:
                    if not task_obj:
                        raise TypeError()
                    task = Task.deserialize(task_obj)
                    if task.status != Task.SUCCESSFUL:
                        # Update task object status
                        task = task._replace(status=Task.FAILED)
                        # Set new status to redis
                        yield from self.connection.set(
                            key,
                            task.serialize(),
                            expire=SETTINGS.TASK_STORAGE_EXPIRE)
                except TypeError as ex:
                    task = None
                    log.error("Wrong task id={}".format(
                        scheduled_task_history.get('scheduled_task_id')),
                              exc_info=True)
                    yield from self.connection.delete([key])

                # Publish message about finish (FAILED)
                if task:
                    yield from self.connection.publish(
                        SETTINGS.TASK_CHANNEL.format(task_id).encode('utf-8'),
                        task.status.encode('utf-8'))
                else:
                    yield from self.connection.publish(
                        SETTINGS.TASK_CHANNEL.format(task_id).encode('utf-8'),
                        Task.FAILED.encode('utf-8'))

                # Update scheduler information
                # Store next_run in scheduled
                try:
                    task_scheduler_obj = yield from self.connection.hget(
                        SETTINGS.SCHEDULER_HISTORY_HASH,
                        scheduled_task_name.encode('utf-8'))
                    task_scheduler = SchedulerTaskHistory.deserialize(
                        task_scheduler_obj)
                    if task and task.status == Task.SUCCESSFUL:
                        scheduled_task_history[
                            'last_run'] = scheduled_task_history.get(
                                'next_run', 0)
                        scheduled_task_history['next_run'] = 0
                        task_scheduler = task_scheduler._replace(
                            last_run=task_scheduler.next_run,
                            next_run=0,
                            scheduled_task_id=None)
                    else:
                        scheduled_task_history['next_run'] = 0
                        scheduled_task_history['scheduled_task_id'] = None
                        task_scheduler = task_scheduler._replace(
                            next_run=0, scheduled_task_id=None)
                    yield from self.connection.hset(
                        SETTINGS.SCHEDULER_HISTORY_HASH,
                        task_scheduler.name.encode('utf-8'),
                        task_scheduler.serialize())
                except:
                    # We lost SCHEDULER_HISTORY_HASH in db
                    if task and task.status == Task.SUCCESSFUL:
                        scheduled_task_history[
                            'last_run'] = scheduled_task_history.get(
                                'next_run', 0)
                        scheduled_task_history['next_run'] = 0
                    else:
                        scheduled_task_history['next_run'] = 0
                        scheduled_task_history['scheduled_task_id'] = None
Example #10
0
def handle_tasks_json():
    return json.dumps(
        [task.to_json() for task in Task.query().fetch(100)])
Example #11
0
def handle_tasks():
    tasks = Task.query().fetch(100)
    return render_template("tasks.html", tasks=tasks)
Example #12
0
 def testModelTask_to_json(self):
     task = Task(name='test',
                 workflow='test workflow',
                 active_nodes=[ndb.Key('Node', 1)],
                 metadata='test metadata')