Example #1
0
    def handle(self, name, arguments):
        """docstring for handle"""

        from tornado.reloaded.utils import get_module_from_import

        try:
            mod = get_module_from_import(name)
        except Exception as e:
            raise Exception('This method doesnt exist : %s' % (e, ))

        for argument in arguments:
            if '=' in argument:
                raise Exception('Kwargs argument is currently not supported')

        mod(*arguments)
Example #2
0
class ZTaskdCommand(Command):
    """docstring for ServerCommand"""
    name = 'ztaskd'
    ioloop = None
    func_cache = {}
    require_env = True
    nb_running = 0
    stop_next = False

    @gen.engine
    def handle(self,
               replay_failed=False,
               max_running=1,
               time_between_check=600):
        """docstring for handle"""

        self.ioloop = IOLoop(ZMQPoller())
        self.ioloop.install()

        self.max_running = max_running
        self.time_between_check = time_between_check
        context = zmq.Context()
        socket = context.socket(zmq.PULL)
        socket.bind("tcp://127.0.0.1:5000")

        self.db = get_db()

        self.periodic = tornado.ioloop.PeriodicCallback(self.run,
                                                        time_between_check *
                                                        1000,
                                                        io_loop=self.ioloop)

        def install_queue_handler(ioloop):
            def _queue_handler(socket, *args, **kwargs):
                try:
                    function_name, args, kwargs, after = socket.recv_pyobj()
                    if function_name == 'ztask_log':
                        logging.warn('%s: %s' % (args[0], args[1]))
                        return

                    datetime.combine(date.today(), time()) + timedelta(hours=1)

                    self.db.ztask.insert(
                        {
                            'function_name':
                            function_name,
                            'args':
                            pickle.dumps(args),
                            'kwargs':
                            pickle.dumps(kwargs),
                            'retry_count':
                            0,
                            'next_attempt':
                            datetime.combine(date.today(), time()) +
                            timedelta(seconds=after)
                        },
                        callback=self._on_insert)

                except Exception, e:
                    logging.error('Error setting up function. Details:\n%s' %
                                  e)
                    traceback.print_exc(e)

            ioloop.add_handler(socket, _queue_handler, ioloop.READ)

        # Reload tasks if necessary
        cursor = None

        # if replay_failed:
        # cursor = self.db.ztask.find()
        # else:
        # cursor = self.db.ztask.find()

        # if cursor is not None:
        # cursor.loop(callback=self._on_select)

        for uid, task in options.scheduled_tasks.items():
            if not 'schedule' in task:
                raise Exception('schedule is required')

            if isinstance(task['schedule'], timedelta):
                module = get_module_from_import(task['task'])
                func = partial(module. async, *task.get('args', []),
                               **task.get('kwargs', {}))
                periodic = tornado.ioloop.PeriodicCallback(
                    func, task['schedule'].seconds * 1000, io_loop=self.ioloop)

                if task.get('run_on_init', False):
                    logging.info('run_on_init for %s enabled' % (uid, ))
                    func()

                logging.info('Starting periodic (%ss) for %s' % (
                    task['schedule'].seconds,
                    uid,
                ))
                periodic.start()

        install_queue_handler(self.ioloop)

        self.run()

        self.periodic.start()

        if 0:  #options.debug:
            from tornado import autoreload
            autoreload.add_reload_hook(
                partial(install_queue_handler, self.ioloop))
            autoreload.start(io_loop=self.ioloop)

        try:
            self.ioloop.start()
        except KeyboardInterrupt:
            if self.stop_next:
                self.ioloop.stop()
            if self.nb_running and not self.stop_next:
                self.stop_next = True
Example #3
0
    def _call_function(self, task_id, callback):
        if self.nb_running < self.max_running:
            self.nb_running += 1
        else:
            return
        try:
            response = yield gen.Task(self.db.ztask.find_one, {'_id': task_id})

            if response:
                function_name = response['function_name']
                args = pickle.loads(str(response['args']))
                kwargs = pickle.loads(str(response['kwargs']))

                if response['retry_count'] >= ZTASKD_RETRY_COUNT:
                    logging.error('Retry count exceeded')
                    self.nb_running -= 1
                    callback()
                    return

            else:
                logging.info('Could not get task with id %s:%s' % (
                    task_id,
                    response,
                ))
                self.nb_running -= 1
                callback()
                return

            logging.info('Calling %s' % (function_name, ))

            if function_name not in self.func_cache:
                self.func_cache[function_name] = get_module_from_import(
                    function_name)

            function = self.func_cache[function_name]

            _ = yield gen.Task(function, *args, **kwargs)
            logging.info('Called %s successfully' % function_name)
            response = yield gen.Task(self.db.ztask.remove, {'_id': task_id})
        except Exception as e:
            logging.exception(e)

            self.db.ztask.update({'_id': task_id}, {
                '$inc': {
                    'retry_count': 1
                },
                '$push': {
                    'logs': {
                        'failed': datetime.utcnow(),
                        'last_exception': '%s' % (e, )
                    }
                },
                '$set': {
                    'next_attempt':
                    datetime.combine(date.today(), time()) +
                    timedelta(seconds=ZTASKD_RETRY_AFTER)
                }
            },
                                 callback=self._on_insert)

            # traceback.print_exc(e)
        finally:
            self.nb_running -= 1
            callback()