如何做API抽象,一个在流水线上实现自缓存能力的例子

通常每个流水线是独立执行的,每次执行的任务之间是无状态的,但是,每次任务都有输入和输出,输入是一个args是json,输出也是一个json,流水线执行环境提供了单次任务输入输出参数的持久化能力。利用这个特点,来实现一个有缓存状态的流水线执行API。

首先,我们把调度平台的流水线的底层API先做一个抽象:

  • 流水线执行API: ret, result = pipeline_run(pipeline_id, args)
    result['task_id'] 是流水线一次执行返回的 task_id

  • 流水线结果获取API: ret, result = pipeline_task_result(task_id)

  • 查询流水线自身最后一次执行task API: ret, result = pipeline_last_task(pipeline_id)
    result['task_id'] 是取到的流水线最后一次执行的task id

  • 存储流水线单次执行结果的API:ret = pipeline_task_result_save(task_id, ret, result)

  • 读取流水线指定 task_id 的结果API:ret, result = pipeline_task_result_get(task_id)

  • 所有的API,ret不为0都算失败

那么,现在使用 python async 实现一个 pipeline_run_continue(pipeline_id, args, continue_id) API,它能反复被执行,执行的时候先取上一次task的结果,如果上一次task的结果里已经含有写入的continu_id,并且status是 SUCCESS,则不重复执行,直接返回结果,否则执行完整的执行、写入结果动作。

import asyncio

async def pipeline_run(pipeline_id, args):
    # 模拟调用流水线执行API
    return 0, {'task_id': 'new_task_id'}

async def pipeline_task_result(task_id):
    # 模拟获取流水线结果API
    return 0, {'status': 'SUCCESS', 'continue_id': 'some_id'}

async def pipeline_last_task(pipeline_id):
    # 模拟查询流水线最后一次执行task API
    return 0, {'task_id': 'last_task_id'}

async def pipeline_task_result_save(task_id, ret, result):
    # 模拟存储流水线单次执行结果的API
    return 0

async def pipeline_task_result_get(task_id):
    # 模拟读取流水线指定task_id的结果API
    return 0, {'status': 'SUCCESS', 'continue_id': 'some_id'}

async def pipeline_run_continue(pipeline_id, args, continue_id):
    # 获取最后一次执行的task
    ret, last_task_result = await pipeline_last_task(pipeline_id)
    if ret != 0:
        return ret, last_task_result

    last_task_id = last_task_result['task_id']

    # 获取最后一次执行的task结果
    ret, result = await pipeline_task_result_get(last_task_id)
    if ret != 0:
        return ret, result

    # 检查结果中是否包含continue_id且状态为SUCCESS
    if result.get('continue_id') == continue_id and result.get('status') == 'SUCCESS':
        return 0, result

    # 执行新的流水线任务
    ret, result = await pipeline_run(pipeline_id, args)
    if ret != 0:
        return ret, result

    new_task_id = result['task_id']

    # 获取新任务的结果
    ret, result = await pipeline_task_result(new_task_id)
    if ret != 0:
        return ret, result

    # 保存新任务的结果
    ret = await pipeline_task_result_save(new_task_id, ret, result)
    if ret != 0:
        return ret, result

    return 0, result

# 示例调用
# asyncio.run(pipeline_run_continue('pipeline_id', 'args', 'continue_id'))

通过这种抽象,前后的流程图差异

新设计流水线执行

开始

调用 pipeline_last_task

获取 last_task_id

调用 pipeline_task_result_get

结果中包含 continue_id 且状态为 SUCCESS?

返回结果

调用 pipeline_run

获取 task_id

调用 pipeline_task_result

获取结果

调用 pipeline_task_result_save

返回结果

传统流水线执行

开始

调用 pipeline_run

获取 task_id

调用 pipeline_task_result

获取结果

返回结果

这个设计的有效之处在于:

  • 缓存状态:通过检查上一次任务的结果,避免了重复执行相同的任务,节省了时间和资源。
  • 持久化能力:利用持久化的输入输出参数,确保每次任务的输入输出可以被记录和重用。
  • 状态检查:通过检查任务结果中的 continue_id 和 status,确保只有在必要时才执行新的任务,提高了效率。

这不是一种常规的开发方式,但是体现了在受限(约束)环境下,做抽象与封装,仍然是写干净代码的最佳方式。要不然就会写出一堆在风中凌乱的意大利面条代码。

--end--

posted @   ffl  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示