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)
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
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()