bugfix
This commit is contained in:
parent
172b7115cb
commit
34ac11fa71
@ -127,12 +127,13 @@ output_ctx使用节点执行结果的字典数据作为数据来渲染,结果u
|
|||||||
* done 执行成功状态
|
* done 执行成功状态
|
||||||
* failed 执行失败状态
|
* failed 执行失败状态
|
||||||
* cancelled 取消状态
|
* cancelled 取消状态
|
||||||
|
* completed 处理完成
|
||||||
状态变化:
|
状态变化:
|
||||||
* pending 转running 如果节点没有join属性,则在下个循环直接转running, 并调用节点执行方法,记录开始执行时间
|
* pending 转running 如果节点有join属性,检查join条件,满足条件就转执行,否则等条件满足, 没有join属性则直接转running, 并调用节点执行方法,记录开始执行时间, 手工节点则由人工点击工作开始转换
|
||||||
* running zhuan done 节点执行成功,并记录完成时间
|
* running zhuan done 节点执行成功,并记录完成时间
|
||||||
* running 转 failed 节点执行失败, 并记录完成时间
|
* running 转 failed 节点执行失败, 并记录完成时间
|
||||||
* pending 转 cancel 取消执行(手工或流程实例被取消)
|
* pending 转 cancel 取消执行(手工或流程实例被取消)
|
||||||
|
* done, cancelled, failed 转 completed 检查从节点出发的边,做节点转移
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.4 subflow_instance
|
### 3.4 subflow_instance
|
||||||
|
|||||||
@ -12,6 +12,7 @@ Features:
|
|||||||
- Query APIs for UI
|
- Query APIs for UI
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from random import randint
|
||||||
from appPublic.log import debug
|
from appPublic.log import debug
|
||||||
from appPublic.timeUtils import timestampstr
|
from appPublic.timeUtils import timestampstr
|
||||||
from sqlor.dbpools import get_sor_context
|
from sqlor.dbpools import get_sor_context
|
||||||
@ -134,25 +135,28 @@ class FlowEngine:
|
|||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Definition / Instance
|
# Definition / Instance
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
def __init__(self):
|
def __init__(self, backid):
|
||||||
self.aio = []
|
self.aio = []
|
||||||
|
self.backid = backid
|
||||||
|
|
||||||
async def bgtask(self):
|
async def bgtask(self):
|
||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
self.aio = []
|
self.aio = []
|
||||||
cnt = 0
|
cnt = 0
|
||||||
while True:
|
while True:
|
||||||
|
aio = []
|
||||||
async with get_sor_context(env, 'dagflow') as sor:
|
async with get_sor_context(env, 'dagflow') as sor:
|
||||||
self.aio = await sor.R('flow_instance', {'status': 'running'})
|
sql = """select * from flow_instance
|
||||||
if cnt >= 60:
|
where backid=${backid}$
|
||||||
debug(f'{self.aio=}')
|
and status = 'running'"""
|
||||||
cnt = 0
|
aio = await sor.sqlExe(sql,{
|
||||||
for r in self.aio:
|
'backid': self.backid
|
||||||
self.step(r.org_id, r.id)
|
})
|
||||||
await asyncio.sleep(2)
|
for r in aio:
|
||||||
cnt += 1
|
self.step(r)
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
async def create_definition(self, org_id, name, version, dsl_text):
|
async def create_definition(self, org_id, name, description, version, dsl_text, ctxfields):
|
||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
async with get_sor_context(env, 'dagflow') as sor:
|
async with get_sor_context(env, 'dagflow') as sor:
|
||||||
fid = env.uuid()
|
fid = env.uuid()
|
||||||
@ -160,7 +164,10 @@ class FlowEngine:
|
|||||||
'id': fid,
|
'id': fid,
|
||||||
'org_id': org_id,
|
'org_id': org_id,
|
||||||
'name': name,
|
'name': name,
|
||||||
|
'description': description,
|
||||||
'version': version,
|
'version': version,
|
||||||
|
'ctxfields': json.dumps(ctxfields),
|
||||||
|
'created_at': timestampstr(),
|
||||||
'dsl': dsl_text
|
'dsl': dsl_text
|
||||||
})
|
})
|
||||||
return fid
|
return fid
|
||||||
@ -169,21 +176,51 @@ class FlowEngine:
|
|||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
async with get_sor_context(env, 'dagflow') as sor:
|
async with get_sor_context(env, 'dagflow') as sor:
|
||||||
iid = env.uuid()
|
iid = env.uuid()
|
||||||
await sor.C('flow_instance', {
|
ns = {
|
||||||
'id': iid,
|
'id': iid,
|
||||||
|
'backid': self.backid,
|
||||||
|
'round': 1,
|
||||||
'org_id': org_id,
|
'org_id': org_id,
|
||||||
'flow_def_id': flow_def_id,
|
'flow_def_id': flow_def_id,
|
||||||
'status': 'running',
|
'status': 'running',
|
||||||
'ctx': json.dumps(ctx or {}),
|
'ctx': json.dumps(ctx or {}),
|
||||||
'active_nodes': json.dumps([])
|
'created_at': timestampstr()
|
||||||
})
|
})
|
||||||
|
await sor.C('flow_instance', ns.copy())
|
||||||
|
await self.create_start_node_execution(sor, ns)
|
||||||
return iid
|
return iid
|
||||||
|
|
||||||
|
async def create_start_node_execution(self, sor, inst):
|
||||||
|
env = ServerEnv()
|
||||||
|
id = env.uuid()
|
||||||
|
await sor.C('node_execution', {
|
||||||
|
'id': id,
|
||||||
|
'type': 'start',
|
||||||
|
'instance_id': inst['id'],
|
||||||
|
'org_id': inst['org_id'],
|
||||||
|
'inst_round': inst['round'],
|
||||||
|
'status': 'done',
|
||||||
|
'node_id': 'start',
|
||||||
|
'created_at': timestampstr()
|
||||||
|
})
|
||||||
|
async def create_end_node_execution(self, sor, inst):
|
||||||
|
env = ServerEnv()
|
||||||
|
id = env.uuid()
|
||||||
|
await sor.C('node_execution', {
|
||||||
|
'id': id,
|
||||||
|
'type': 'end',
|
||||||
|
'instance_id': inst['id'],
|
||||||
|
'org_id': inst['org_id'],
|
||||||
|
'inst_round': inst['round'],
|
||||||
|
'status': 'pending',
|
||||||
|
'node_id': 'end',
|
||||||
|
'created_at': timestampstr()
|
||||||
|
})
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Execution
|
# Execution
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
|
||||||
async def step(self, org_id, instance_id):
|
async def step(self, inst):
|
||||||
"""
|
"""
|
||||||
从节点执行表中取出所有状态不是结束的执行节点,检查是否可以推进一步
|
从节点执行表中取出所有状态不是结束的执行节点,检查是否可以推进一步
|
||||||
结束状态为:
|
结束状态为:
|
||||||
@ -193,17 +230,6 @@ class FlowEngine:
|
|||||||
推进:如果
|
推进:如果
|
||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
async with get_sor_context(env, 'dagflow') as sor:
|
async with get_sor_context(env, 'dagflow') as sor:
|
||||||
insts = await sor.R('flow_instance', {
|
|
||||||
'id': instance_id,
|
|
||||||
'org_id': org_id
|
|
||||||
})
|
|
||||||
if not insts:
|
|
||||||
return
|
|
||||||
|
|
||||||
inst = insts[0]
|
|
||||||
if inst['status'] != 'running':
|
|
||||||
return
|
|
||||||
|
|
||||||
flow_def = (await sor.R(
|
flow_def = (await sor.R(
|
||||||
'flow_definition',
|
'flow_definition',
|
||||||
{'id': inst['flow_def_id']}
|
{'id': inst['flow_def_id']}
|
||||||
@ -213,85 +239,78 @@ class FlowEngine:
|
|||||||
ctx = json.loads(inst['ctx'])
|
ctx = json.loads(inst['ctx'])
|
||||||
active = set(json.loads(inst['active_nodes']) or [dsl['start']])
|
active = set(json.loads(inst['active_nodes']) or [dsl['start']])
|
||||||
next_nodes = set()
|
next_nodes = set()
|
||||||
|
sql = "select * from node_execution where instance_id=${instance_id}$ and status != 'completed'"
|
||||||
for node_id in active:
|
active_nes = await sor.sqlExe(sql, {
|
||||||
|
'instance_id': inst.id
|
||||||
|
})
|
||||||
|
for ne in active_nes:
|
||||||
|
node_id = ne.node_id
|
||||||
node = dsl['nodes'][node_id]
|
node = dsl['nodes'][node_id]
|
||||||
|
node['id'] = node_id
|
||||||
ntype = node['type']
|
ntype = node['type']
|
||||||
|
status = ne.status
|
||||||
# -------- Human node --------
|
if status == 'pending':
|
||||||
if ntype == 'human':
|
if ntype == 'human':
|
||||||
rows = await sor.R('human_task', {
|
if ne.assignee is None:
|
||||||
'instance_id': instance_id,
|
await self.auto_assign(sor, inst, ne, node)
|
||||||
'node_id': node_id,
|
elif ntype == 'task':
|
||||||
'status': 'pending'
|
await self.try_start_running(sor, inst, ne, node)
|
||||||
|
elif ntype == 'subflow':
|
||||||
|
await self.try_start_subflow(sor, inst, ne, node)
|
||||||
|
elif ntype == 'start':
|
||||||
|
await self.node_transfer(sor, inst, ne, node, flow_def)
|
||||||
|
await sor.U('node_execution', {
|
||||||
|
'id': ne.id,
|
||||||
|
'status': 'completed'
|
||||||
})
|
})
|
||||||
if not rows:
|
elif ntype == 'end':
|
||||||
await sor.C('human_task', {
|
flg = await self.is_ok_to_step_next(sor, node, edges, inst)
|
||||||
'id': env.uuid(),
|
if flg:
|
||||||
'org_id': org_id,
|
await sor.U('node_execution', {
|
||||||
'instance_id': instance_id,
|
'id': ne.id,
|
||||||
'node_id': node_id,
|
'status': 'completed'
|
||||||
'role': node.get('role'),
|
|
||||||
'status': 'pending',
|
|
||||||
'input': json.dumps(ctx),
|
|
||||||
'timeout_at': env.after(node.get('timeout', 0))
|
|
||||||
})
|
})
|
||||||
next_nodes.add(node_id)
|
|
||||||
continue
|
|
||||||
if ntype == 'task':
|
|
||||||
if node.get('join'):
|
|
||||||
await sor.C('node_execution', {
|
|
||||||
'id': env.uuid(),
|
|
||||||
'org_id': org_id,
|
|
||||||
'instance_id': instance_id,
|
|
||||||
'node_id': node_id,
|
|
||||||
'input_ctx': json.dumps(ctx),
|
|
||||||
'status': 'pendding'
|
|
||||||
})
|
|
||||||
|
|
||||||
# ---- 如果节点状态在pending状态 ---
|
|
||||||
if node['status'] == 'pending' and ntype != 'human':
|
|
||||||
is_ok = await self.is_ok_to_start(sor, node, inst)
|
|
||||||
if is_ok:
|
|
||||||
await self.start_running(sor, node)
|
|
||||||
continue
|
|
||||||
# -------- Normal node --------
|
|
||||||
"""
|
|
||||||
await sor.C('node_execution', {
|
|
||||||
'id': env.uuid(),
|
|
||||||
'org_id': org_id,
|
|
||||||
'instance_id': instance_id,
|
|
||||||
'node_id': node_id,
|
|
||||||
'input_ctx': json.dumps(ctx),
|
|
||||||
'status': 'pendding'
|
|
||||||
})
|
|
||||||
"""
|
|
||||||
if nstatus == 'done' or nstatus == 'failed':
|
|
||||||
n_nodes = await self.node_transfer(node, dsl)
|
|
||||||
next_nodes += n_nodes
|
|
||||||
|
|
||||||
if next_nodes and all(dsl['nodes'][n]['type'] == 'end' for n in next_nodes):
|
|
||||||
await sor.U('flow_instance', {
|
await sor.U('flow_instance', {
|
||||||
'id': instance_id,
|
'id': inst.id,
|
||||||
'status': 'finished',
|
'status': 'completed'
|
||||||
'active_nodes': json.dumps(list(next_nodes))
|
|
||||||
})
|
})
|
||||||
else:
|
break;
|
||||||
await sor.U('flow_instance', {
|
elif status in ['done', 'cancelled', 'failed']:
|
||||||
'id': instance_id,
|
await self.node_transfer(sor, inst, ne, node, flow_def)
|
||||||
'active_nodes': json.dumps(list(next_nodes))
|
await sor.U('node_execution', {
|
||||||
|
'id': ne.id,
|
||||||
|
'status': 'completed'
|
||||||
})
|
})
|
||||||
|
self.check_instance_completed(sor, inst)
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Human task APIs
|
# Human task APIs
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
|
||||||
async def node_transfer(self, node):
|
async def auto_assign(self, sor, inst, ne, node):
|
||||||
if node['status'] not in ['done', 'failed', 'cancel']:
|
recs = await env.get_org_users(sor, inst.org_id, ne.role)
|
||||||
return
|
if recs:
|
||||||
|
i = randint(len(recs) - 1)
|
||||||
|
await sor.U('node_execution', {
|
||||||
|
'id':ne.id,
|
||||||
|
'assignee': recs[i].id
|
||||||
|
})
|
||||||
|
|
||||||
|
async def check_instance_completed(self, sor, inst):
|
||||||
|
sql = "select * from node_execution where instance_id=${instance_id} and type='end'"
|
||||||
|
recs = await sor.sqlExe(sql, {'instance_id', inst.id})
|
||||||
|
if recs:
|
||||||
|
if recs[0].status == 'completed':
|
||||||
|
await sor.U('flow_instance', {
|
||||||
|
'id': inst.id,
|
||||||
|
'status': 'completed'
|
||||||
|
})
|
||||||
|
|
||||||
|
async def node_transfer(self, sor, dsl, inst, ne, node, flow_def):
|
||||||
nnode = []
|
nnode = []
|
||||||
for edge in dsl.get('edges', []):
|
for edge in dsl.get('edges', []):
|
||||||
if edge['from'] != node_id:
|
if edge['from'] != ne.node_id:
|
||||||
continue
|
continue
|
||||||
cond = edge.get('when')
|
cond = edge.get('when')
|
||||||
if cond and not eval(cond, {}, {'ctx': ctx}):
|
if cond and not eval(cond, {}, {'ctx': ctx}):
|
||||||
@ -305,7 +324,47 @@ class FlowEngine:
|
|||||||
on_array = await self.get_multiple_array(m_on):
|
on_array = await self.get_multiple_array(m_on):
|
||||||
for e in on_array:
|
for e in on_array:
|
||||||
nnodes.add((edge['to'], str(e)))
|
nnodes.add((edge['to'], str(e)))
|
||||||
return nnodes
|
for node, ctx_ext in nnodes:
|
||||||
|
x = await self.is_ok_to_create_new_node_exe(sor, node, edges, inst)
|
||||||
|
if x:
|
||||||
|
env = ServerEnv()
|
||||||
|
id = env.uuid()
|
||||||
|
ns = {
|
||||||
|
'id': id,
|
||||||
|
'type': node['type'],
|
||||||
|
'inst_round': inst.round,
|
||||||
|
'org_id': inst.org_id,
|
||||||
|
'node_id': node['id'],
|
||||||
|
'input_ctx': node.get('input_ctx'),
|
||||||
|
'output_ctx': node.get('output_ctx'),
|
||||||
|
'status': 'pending',
|
||||||
|
'ctx': json.dumps(inst.ctx.copy(), ensure_ascii=False),
|
||||||
|
'ctx_ext': json.dumps(ctx_ext.copy(), ensure_ascii=False),
|
||||||
|
'created_at': timestampstr()
|
||||||
|
}
|
||||||
|
if node['type'] == 'human':
|
||||||
|
ns.update({
|
||||||
|
'role': node.get('role')
|
||||||
|
})
|
||||||
|
elif node['type'] == 'task':
|
||||||
|
pass
|
||||||
|
elif node['type'] == 'subflow':
|
||||||
|
eng = env.template_engine
|
||||||
|
ctx = inst.ctx
|
||||||
|
if node.get('input_ctx'):
|
||||||
|
ctx = eng.renders(node['input_ctx'], ctx)
|
||||||
|
|
||||||
|
subinst_id = await self.create_instance(org_id, node.flow_def_id, ctx=ctx)
|
||||||
|
ns.update({
|
||||||
|
'subinst_id': subinst_id
|
||||||
|
})
|
||||||
|
elif node['type'] == 'end':
|
||||||
|
ns.update('
|
||||||
|
await self.create_end_node_execution(sor, inst)
|
||||||
|
|
||||||
|
await sor.C('node_execution', ns)
|
||||||
|
|
||||||
|
if node.join
|
||||||
|
|
||||||
async def is_ok_to_create_new_node_exe(self, sor, node, edges, inst):
|
async def is_ok_to_create_new_node_exe(self, sor, node, edges, inst):
|
||||||
join = node.get('join)
|
join = node.get('join)
|
||||||
@ -331,7 +390,7 @@ class FlowEngine:
|
|||||||
})
|
})
|
||||||
return id
|
return id
|
||||||
|
|
||||||
async def is_ok_to_start(self, sor, node, edges, inst):
|
async def is_ok_to_step_next(self, sor, node, edges, inst):
|
||||||
join = node.get('join')
|
join = node.get('join')
|
||||||
if not join:
|
if not join:
|
||||||
return True
|
return True
|
||||||
@ -439,28 +498,24 @@ where instance_id=${instance_id}$
|
|||||||
'ctx': json.dumps(ctx)
|
'ctx': json.dumps(ctx)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def get_engine():
|
||||||
|
env = ServerEnv()
|
||||||
|
cnt = len(env.flow_engines)
|
||||||
|
id = randint(cnt-1)
|
||||||
|
return env.flow_engines[id]
|
||||||
|
|
||||||
async def add_new_workflow(request, params_kw={}):
|
async def add_new_workflow(request, params_kw={}):
|
||||||
name = params_kw.name
|
name = params_kw.name
|
||||||
dsl = params_kw.dsl
|
dsl = params_kw.dsl
|
||||||
env = request._run_ns
|
env = request._run_ns
|
||||||
orgid = await env.get_userorgid()
|
orgid = await env.get_userorgid()
|
||||||
async with get_sor_context(env, 'dagflow') as sor:
|
ctxfileds = params_kw.ctxfields or []
|
||||||
ns = {
|
description = params_kw.description
|
||||||
'id': env.uuid(),
|
engine = get_engine()
|
||||||
'name': name,
|
id = await engine.create_definition(org_id, name, description, '1', dsl, ctxfields)
|
||||||
'dsl': dsl,
|
|
||||||
'version': '1',
|
|
||||||
'created_at': timestampstr(),
|
|
||||||
'org_id': orgid
|
|
||||||
}
|
|
||||||
await sor.C('dagflow_definition', ns)
|
|
||||||
return {
|
return {
|
||||||
'status': 'SUCCEEDED',
|
'status': 'SUCCEEDED',
|
||||||
'data': {
|
'data': {
|
||||||
'dagflow_id': ns['id']
|
'dagflow_id': id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
|
||||||
'status': 'FAILED',
|
|
||||||
'error': 'add workflow error'
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,18 +1,29 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from appPublic.jsonConfig import getConfig
|
||||||
from ahserver.serverenv import ServerEnv
|
from ahserver.serverenv import ServerEnv
|
||||||
from ahserver.configuredServer import add_cleanupctx
|
from ahserver.configuredServer import add_cleanupctx
|
||||||
from .dagflow import FlowEngine
|
from .dagflow import FlowEngine
|
||||||
|
|
||||||
async def dagbacktask(engine, app):
|
async def dagbacktask(engines, app):
|
||||||
task = asyncio.create_task(engine.bgtask())
|
tasks = []
|
||||||
|
for e in engines:
|
||||||
|
task = asyncio.create_task(e.bgtask())
|
||||||
|
tasks.append(task)
|
||||||
yield
|
yield
|
||||||
|
for task in tasks:
|
||||||
task.cancel()
|
task.cancel()
|
||||||
|
|
||||||
def load_dagflow():
|
def load_dagflow():
|
||||||
engine = FlowEngine()
|
config = getConfig()
|
||||||
f = partial(dagbacktask, engine)
|
flow_engines = []
|
||||||
|
cnt = config.dagflow_job_cnt or 1
|
||||||
|
for i in range(cnt):
|
||||||
|
e = FlowEngine(i)
|
||||||
|
flow_engines.append(e)
|
||||||
|
|
||||||
|
f = partial(dagbacktask, flow_engines)
|
||||||
add_cleanupctx(f)
|
add_cleanupctx(f)
|
||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
env.workflow_engine = engine
|
env.flow_engines = flow_engines
|
||||||
|
|
||||||
|
|||||||
@ -7,11 +7,12 @@
|
|||||||
}],
|
}],
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "id", "title": "实例ID", "type": "str", "length": 32, "nullable": "no"},
|
{"name": "id", "title": "实例ID", "type": "str", "length": 32, "nullable": "no"},
|
||||||
|
{"name": "backid", "title": "后台id", "type": "short", "nullable": "no"},
|
||||||
|
{"name": "round", "title": "当前论次", "type": "short"},
|
||||||
{"name": "org_id", "title": "机构id", "type": "str", "length": 32, "nullable": "no"},
|
{"name": "org_id", "title": "机构id", "type": "str", "length": 32, "nullable": "no"},
|
||||||
{"name": "flow_def_id", "title": "流程定义ID", "type": "str", "length": 32},
|
{"name": "flow_def_id", "title": "流程定义ID", "type": "str", "length": 32},
|
||||||
{"name": "status", "title": "状态", "type": "str", "length": 16},
|
{"name": "status", "title": "状态", "type": "str", "length": 16},
|
||||||
{"name": "ctx", "title": "上下文(JSON)", "type": "text"},
|
{"name": "ctx", "title": "上下文(JSON)", "type": "text"},
|
||||||
{"name": "active_nodes", "title": "当前节点(JSON)", "type": "text"},
|
|
||||||
{"name": "created_at", "title": "创建时间", "type": "timestamp"}
|
{"name": "created_at", "title": "创建时间", "type": "timestamp"}
|
||||||
],
|
],
|
||||||
"indexes": [
|
"indexes": [
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{"name": "id", "title": "执行ID", "type": "str", "length": 32, "nullable": "no"},
|
{"name": "id", "title": "执行ID", "type": "str", "length": 32, "nullable": "no"},
|
||||||
{"name": "type", "title": "节点类型", "type": "str", "length": 32},
|
{"name": "type", "title": "节点类型", "type": "str", "length": 32},
|
||||||
|
{"name": "inst_round", "title": "执行论次", "type": "short"},
|
||||||
{"name": "org_id", "title": "机构id", "type": "str", "length": 32},
|
{"name": "org_id", "title": "机构id", "type": "str", "length": 32},
|
||||||
{"name": "instance_id", "title": "流程实例ID", "type": "str", "length": 32},
|
{"name": "instance_id", "title": "流程实例ID", "type": "str", "length": 32},
|
||||||
{"name": "node_id", "title": "节点ID", "type": "str", "length": 64},
|
{"name": "node_id", "title": "节点ID", "type": "str", "length": 64},
|
||||||
@ -25,7 +26,6 @@
|
|||||||
{"name": "running_at", "title": "执行时点", "type": "timestamp"},
|
{"name": "running_at", "title": "执行时点", "type": "timestamp"},
|
||||||
{"name": "stopping_at", "title": "结束时点", "type": "timestamp"},
|
{"name": "stopping_at", "title": "结束时点", "type": "timestamp"},
|
||||||
{"name": "created_at", "title": "执行时间", "type": "timestamp"}
|
{"name": "created_at", "title": "执行时间", "type": "timestamp"}
|
||||||
{"name": "next_nodeid", "title": "下一节点id", "type", "str", "length": 32}
|
|
||||||
],
|
],
|
||||||
"indexes": [
|
"indexes": [
|
||||||
{"name": "idx_node_exec_inst", "idxtype": "index", "idxfields": ["instance_id"]}
|
{"name": "idx_node_exec_inst", "idxtype": "index", "idxfields": ["instance_id"]}
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [{
|
|
||||||
"name": "subflow_instance",
|
|
||||||
"title": "子流程实例",
|
|
||||||
"primary": "id",
|
|
||||||
"catelog": "relation"
|
|
||||||
}],
|
|
||||||
"fields": [
|
|
||||||
{"name": "id", "title": "子流程ID", "type": "str", "length": 32, "nullable": "no"},
|
|
||||||
{"name": "parent_instance_id", "title": "父流程实例ID", "type": "str", "length": 32},
|
|
||||||
{"name": "parent_node_id", "title": "父节点ID", "type": "str", "length": 64},
|
|
||||||
{"name": "child_instance_id", "title": "子流程实例ID", "type": "str", "length": 32},
|
|
||||||
{"name": "status", "title": "状态", "type": "str", "length": 16},
|
|
||||||
{"name": "created_at", "title": "创建时间", "type": "timestamp"}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{"name": "idx_subflow_parent", "idxtype": "index", "idxfields": ["parent_instance_id"]},
|
|
||||||
{"name": "idx_node_exec_inst", "idxtype": "index", "idxfields": ["instance_id"]}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user