def check_redo_switches(t): pt = t.period[-1:] pv = t.period[:-1] t.parameters['start_date'] = datetime.now() - get_offset(pv, pt) r = execute(t.target , "select count(1) switches_count from v$log_history" " where first_time > :start_date having count(1) >= :switches_per_interval" , {'start_date': t.parameters['start_date'] , 'switches_per_interval': t.parameters['switches_per_interval']} , 'one' , False) return f'Redo logs on {t.target} have been switched {str(r[0])} times in the last {t.period}.' if r else None
def wait_for_queued(t): pt = t.period[-1:] pv = t.period[:-1] t.parameters['start_date'] = datetime.now() - get_offset(pv, pt) r = execute(t.target , "select nvl(sql_id, 'Unknown sql') || ' ' || event || ' ' || to_char(session_id), " " nvl(sql_id, 'Unknown sql'), event, session_id, machine, count(1) waits" " from v$active_session_history" " where event like 'enq:%' and sample_time > :start_date" " and event not like :ignore_event" " group by nvl(sql_id, 'Unknown sql') || ' ' || event || ' ' || to_char(session_id)," " sql_id, event, session_id, machine" " having count(1) > :queued_time_sec" , {'start_date': t.parameters['start_date'] , 'queued_time_sec': t.parameters['queued_time_sec'] , 'ignore_event': t.optional.get('ignore_event', '---')} , 'many' , False) return t.get_message(r, lambda o, i: '{} ({}, {}) on {} has been queued for {} seconds ({}).' .format(t_link(f'{t.target}/Q/{i[1]}', i[1]), i[4], i[3], t.target, i[5], i[2]), None, 0)
def run(self): while self.active: # Now dnd means "send with no sound". Formerly tasks did were't processing at dnd hours. # if check_dnd_time(): # sleep(app.config['WORKER_FREQ_SEC']) # continue with lock: active_tasks = tuple(t for t in sorted(task_pool.values(), key=lambda x: x.priority) if t.state == 'wait') for task in active_tasks: with lock: if not task_pool.get(task.uuid): continue if task.last_call: pt = task.period[-1:] pv = task.period[:-1] next_call = task.last_call + get_offset(pv, pt) if next_call > datetime.now(): continue task.state = 'run' try: task_start_time = datetime.now() message = app.view_functions[task.endpoint](task) r = 0 if message: if task.text: message = f'{t_italic(task.text)}\n{message}' notification_pool.appendleft( (datetime.now(), task.uuid, task.name, message)) if task.chat_id and not app.config['MUTE_MESSAGES']: r = prepare_and_send(task.chat_id, task.reply_to_message_id, message, task.sound) if r != 0: unsent_pool.appendleft( (datetime.now(), task.uuid, task.name, task.chat_id, task.reply_to_message_id, message)) if task.finished: del task_pool[task.uuid] else: task.last_call = datetime.now() task.duration = (task.last_call - task_start_time).seconds task.execs += 1 task.state = 'wait' if r == 0 or not app.config[ 'FAIL_TASK_ON_MSG_ERROR'] else 'msg error' # retry sending even if prev msg had no recipient if r == 0 and message and not app.config['MUTE_MESSAGES']: while r == 0 and len(unsent_pool) > 0: m = unsent_pool.popleft() r = prepare_and_send( m[3], m[4], f'{t_italic("This message was postponed due to network problem")}' f'\n{m[5]}', 'default') if r == 0 and task_pool.get(m[1], None): task_pool[m[1]].state = 'wait' if r != 0: unsent_pool.appendleft(m) except (DatabaseError, OperationalError) as e: app.logger.error(f'{task.uuid} {e.args[0].message}') task.state = 'db error' sleep(app.config['WORKER_FREQ_SEC'])