def initialize_periodic_calls(): for pcall in PERIODIC_CALLS: name = pcall['name'] pattern = pcall.get('pattern') or CONF.get('cron', name) pcall_db = api.get_periodic_call_by_name(name) start_time = datetime.datetime.now() next_time = croniter(pattern, start_time).get_next(datetime.datetime) target_method = pcall['func_path'] arguments = pcall.get('arguments', {}) values = { 'execution_time': next_time, 'pattern': pattern, 'target_method': target_method, 'arguments': json.dumps(arguments), 'processing': False } if not pcall_db: values.update({'name': name}) pcall_db = api.create_periodic_call(values) else: pcall_db = api.update_periodic_call(name, values) SEMAPHORES[pcall_db.id] = semaphore.Semaphore(pcall.get('threads', 1))
def end_processing(gt, pcall): next_time = get_next_time( pcall.pattern, datetime.datetime.now() ) next_time2 = get_next_time( pcall.pattern, pcall.execution_time ) api.update_periodic_call( pcall.name, { 'execution_time': max(next_time, next_time2), 'processing': False } ) SEMAPHORES[pcall.id].release()
def process_periodic_calls(): """Long running thread processing next periodic calls :return: """ while True: calls_to_process = get_next_periodic_calls() while not calls_to_process: calls = api.get_periodic_calls() now = datetime.datetime.now() nearest = min([c.execution_time for c in calls]) time_to_sleep = (nearest - now).total_seconds() time_to_sleep = time_to_sleep if time_to_sleep > 0 else 1 LOG.debug("Sleeping for %s s..." % time_to_sleep) time.sleep(time_to_sleep) calls_to_process = get_next_periodic_calls() for call in calls_to_process: func = utils.import_class(call.target_method) arguments = json.loads(call.arguments) api.update_periodic_call( call.name, { 'execution_time': get_next_time( call.pattern, call.execution_time ), 'processing': True } ) SEMAPHORES[call.id].acquire() t = eventlet.spawn(func, **arguments) t.link(end_processing, call)