Пример #1
0
def rpc_push_job(exec_id, interface_id, job_id, server_host, port, params_value, server_dir, server_script, return_code,
                 status, date_format='%Y%m%d', run_date=''):
    """
    RPC分发任务
    1.替换$date变量
    :param exec_id: 执行id
    :param interface_id: 任务流id
    :param job_id: 任务id
    :param server_host: RPC执行服务器域名
    :param port: RPC执行服务器端口
    :param params_value: 参数值字符串
    :param server_dir: 脚本目录
    :param server_script: 运行脚本
    :param return_code: 状态返回码
    :param status: 任务状态
    :param date_format: 日期格式
    :param run_date: 数据日期
    :return: 
    """""
    try:
        # rpc分发任务
        client = Connection(server_host, port)
        # 任务参数中数据日期变量为T-1
        if not run_date:
            run_time = (date.today() + timedelta(days=-1)).strftime(date_format)
        else:
            run_time = run_date
        params = params_value.split(',') if params_value else []
        client.rpc.event_execute(
            exec_id=exec_id,
            interface_id=interface_id,
            job_id=job_id,
            server_dir=server_dir,
            server_script=server_script,
            return_code=return_code,
            params=[item if item != '$date' else run_time for item in params],
            status=status
        )
        client.disconnect()
        return ''
    except:
        err_msg = 'rpc连接异常: host: %s, port: %s' % (server_host, port)
        # 添加执行任务详情日志
        EventModel.add_event_exec_detail_job(db.etl_db, exec_id, interface_id, job_id, 'ERROR', server_dir,
                                             server_script, err_msg, 3)
        # 修改数据库, 分布式锁
        with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
            # 修改执行详情表状态[失败]
            EventModel.update_event_exec_job_status(db.etl_db, exec_id, interface_id, job_id, 'failed')
            # 修改执行任务流状态[失败]
            EventModel.update_event_exec_interface_status(db.etl_db, exec_id, interface_id, -1)
            # 修改执行主表状态[失败]
            EventModel.update_event_execute_status(db.etl_db, exec_id, -1)
        log.error(err_msg, exc_info=True)
        return err_msg
Пример #2
0
def continue_event_execute_interface(exec_id, result=None, exec_type=1, run_date=''):
    """
    获取事件可执行任务流
    1.如果所有执行任务流都完成, 修改执行主表状态[成功]
    2.所有任务流都完成, 修改执行主表状态[成功], 返回退出
    3.获取当前执行id下的任务流, 遍历任务流
    3.自动调度下(exec_type=1)当前节点出度的所有入度成功, 出度的所有入度数据日期>=出度的数据日期, 节点出度的状态为待运行;
      手动调度下(exec_type=2)默认所有出度成功.
    4.获取可执行任务流下初始任务, 存在空任务流, 修改执行任务流状态[成功], 修改任务流数据日期, 递归本方法
    5.否则修改执行任务流状态[运行中], 返回结果集
    :param result: 结果集
    :param exec_id: 执行id
    :param exec_type: 执行类型: 1.自动, 2.手动
    :param run_date: 数据日期
    :return:
    """
    if not run_date:
        run_date = time.strftime('%Y-%m-%d', time.localtime())
    # 可执行任务流id
    if result is None:
        result = {}
    next_interface = []
    # {可执行任务流id: {'job_id': [可执行任务id], 'nodes': {'job_id': {任务详情}}}}
    # 推进流程
    with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
        interface_dict = get_event_interface_dag_by_exec_id(exec_id)
    # 已完成任务流
    complete_interface = [_ for _, item in interface_dict.items() if item['status'] == 0]
    # 所有任务流都完成
    if len(complete_interface) == len(interface_dict):
        # 修改执行主表状态[成功]
        with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
            EventModel.update_event_execute_status(db.etl_db, exec_id, 0)
        return
    # 遍历所有节点
    for interface_id in interface_dict:
        # 自动调度下, 检查出度的入度数据日期和状态是否成功
        if exec_type == 1:
            # 出度任务流的执行详情
            with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
                current_detail = EventModel.get_event_interface_detail_last_execute(db.etl_db, interface_id)
            for out_id in interface_dict[interface_id]['out_degree']:
                flag = True
                for in_id in interface_dict[out_id]['in_degree']:
                    # 获取出度的入度任务流详情
                    with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
                        in_detail = EventModel.get_event_interface_detail_last_execute(db.etl_db, in_id)
                    # 1.出度的入度本次执行状态不成功, 2.如果存在出度的上一次执行记录, 上一次执行记录不成功
                    if in_detail['status'] != 0 \
                            or (current_detail['last_status'] and current_detail['last_status'] != 0):
                        flag = False
                        break
                if flag and interface_dict[out_id]['status'] == 3:
                    next_interface.append(out_id)
        # 手动调度下, 直接通过
        else:
            for out_id in interface_dict[interface_id]['out_degree']:
                flag = True
                for in_id in interface_dict[out_id]['in_degree']:
                    # 获取出度的入度详情
                    with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
                        in_detail = EventModel.get_event_interface_detail_last_execute(db.etl_db, in_id)
                    # 1.出度的入度本次执行状态不成功
                    if in_detail['status'] != 0:
                        flag = False
                        break
                if flag and interface_dict[out_id]['status'] == 3:
                    next_interface.append(out_id)
        # 获取所有层级可执行任务
        for next_interface_id in set(next_interface):
            nodes = get_event_job_dag_by_exec_id(exec_id, next_interface_id)
            # 可执行任务流设置默认可执行任务
            result.setdefault(next_interface_id, {'nodes': nodes, 'job_id': []})
            # 遍历所有节点
            for job_id in nodes:
                # 初始节点
                if nodes[job_id]['level'] == 0 and nodes[job_id]['status'] in ('preparing', 'ready'):
                    result[next_interface_id]['job_id'].append(job_id)
    # 出度任务流中符合条件的任务为空, 寻找下一个可执行任务流
    flag = False
    result_deep = deepcopy(result)
    for interface_id, item in result_deep.items():
        # 修改执行任务流状态[成功]
        if not item['job_id']:
            flag = True
            result.pop(interface_id)
            log.info('任务流中任务为空: 执行id: %s, 任务流id: %s' % (exec_id, interface_id))
            with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
                EventModel.update_event_exec_interface_status(db.etl_db, exec_id, interface_id, 0)
        # 修改执行任务流状态[运行中]
        else:
            with MysqlLock(config.mysql.etl, 'event_lock_%s' % exec_id):
                EventModel.update_event_exec_interface_status(db.etl_db, exec_id, interface_id, 1)
    # 存在空任务流
    if flag:
        return continue_event_execute_interface(exec_id, result, exec_type, run_date)
    else:
        return result