函数库与调用接口
函数库保存用户自己写的 Python 函数,并提供调试、语法检查和执行三类能力。执行环境与执行器实现分别见隔离 Python 执行环境配置和隔离 Python 执行器。
一、存储
迁移脚本 scripts/006-python-functions.sql 新增函数存储表,可重复执行初始化脚本应用迁移,已有数据保留:
.\scripts\Initialize-Database.ps1 -PostgresBin '<PostgreSQL安装目录>\bin'
| 字段 | 含义 |
|---|---|
id | 雪花 ID |
user_id | 归属用户 |
name / desc | 名称与描述 |
code | 函数源码 |
input_field_list | 调用参数定义(名称、类型、是否必填) |
init_field_list | 初始化参数定义 |
init_params | 初始化参数值,按函数保存 |
permission_type | PRIVATE 或 PUBLIC |
is_active | 是否启用 |
删除是软删除(deleted=true),已保存的函数可以随时重新启用。
二、接口
接口都要求登录,并且只允许操作自己的函数:
| 方法与路径 | 功能 |
|---|---|
GET /api/function_lib | 函数列表,最多 100 条 |
GET /api/function_lib/{page}/{size} | 分页函数列表 |
POST /api/function_lib | 创建函数 |
GET /api/function_lib/{id} | 查看函数 |
PUT /api/function_lib/{id} | 修改自己的函数 |
DELETE /api/function_lib/{id} | 软删除自己的函数 |
POST /api/function_lib/debug | 调试尚未保存的代码 |
POST /api/function_lib/pylint | 语法检查,返回行列诊断 |
POST /api/function_lib/{id}/execute | 执行自己保存且已启用的函数 |
pylint 只在执行环境里做语法检查,返回前端可用的行列信息,不等同于完整 Pylint 规则集。
三、参数
调试请求
POST /api/function_lib/debug 的请求体沿用原版前端的字段结构:
{
"code": "def add(a, b):\n return a + b",
"entrypoint": "add",
"init_params": { "a": 1, "b": 1 },
"input_field_list": [
{ "name": "a", "type": "int", "is_required": true },
{ "name": "b", "type": "int", "is_required": true }
],
"debug_field_list": [
{ "name": "a", "value": "2" },
{ "name": "b", "value": "40" }
]
}
init_params 是保存函数时带下来的初始值;debug_field_list 是这次调试输入的值,按字段名覆盖初始值;input_field_list 决定字段类型和必填校验。上例返回 42。
类型与合并规则
支持 string、int、float、dict、array 五种类型,转换在 Java 侧完成:
| 类型 | 转换结果 |
|---|---|
int | Long |
float | Double |
dict | JSON 对象 |
array | JSON 数组 |
其它/string | 字符串 |
保存函数的初始化参数与调用参数合并后一起传入 Python,调用参数优先。必填字段缺失时直接拒绝,返回 缺少函数参数:<名称>,不会进入执行环境。公开函数的列表接口不会向其他用户返回 init_params 的值。
入口函数规则:请求里给了 entrypoint 就用它,否则取源码中最后一个顶层函数;两者都取不到时返回"代码需要至少一个顶层函数"。
四、执行
POST /api/function_lib/{id}/execute 执行自己保存且启用的函数,请求体是调用参数对象,内部合并该函数的 init_params 后交给执行器。函数不存在、已停用或不属于当前用户时直接拒绝。
保存的函数也可以被后续工作流节点复用:共享入口是 PythonFunctionService.execute,由节点传入应用侧参数。这只是一个可复用的执行入口,不代表任意原版工作流节点都已经兼容。
这个接口目前只面向 Java 侧调用方,前端界面没有对应入口(编辑器走的是调试与语法检查两条路径)。
五、返回与错误
调试接口返回函数返回值本身,执行单元内部的异常会作为失败信息返回,便于前端直接展示:
| 情况 | 返回 |
|---|---|
| 正常返回 | {"code":200,"data":<返回值>} |
| 函数内异常 | division by zero 之类的原始信息 |
| 缺少必填参数 | 缺少函数参数:a |
| 没有顶层函数 | 代码需要至少一个顶层函数 |
| 入口函数不存在 | 入口函数不存在 |
| 返回值超过 256 KiB | 函数返回结果超过 256 KiB |
| 代码超过 64 KiB | Python 代码不能为空且不能超过 64 KiB |
| 语法检查命中错误 | 行列诊断列表(不是失败响应) |
执行环境不可用时的错误文案见隔离 Python 执行器第五节。
六、验证
mvn '-Dtest=IsolatedPythonExecutorTest' '-Dsurefire.failIfNoSpecifiedTests=false' '-Dmaven.javadoc.skip=true' '-Dgpg.skip=true' test
接口层已在运行实例上核对过:按上面的字段结构调试 2 + 40 得到 42;缺少必填参数返回"缺少函数参数";函数内 1/0 返回 division by zero;返回 300000 字符的字符串被拒绝;pylint 对语法错误返回行列信息;无顶层函数被拒绝;执行结束后远程引擎上没有残留的执行容器。
相关章节
- 隔离 Python 执行环境配置:Docker over TCP、宿主沙箱与边界对比。
- 隔离 Python 执行器:交换协议、资源限制与失败语义。
