Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 任务调试历史查询 & 交互优化 #23 #24

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions bkflow/apigw/docs/zh/create_mock_task.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@

#### 接口参数

| 字段 | 类型 | 必选 | 描述 |
|-------------|--------|----|----------------------------------------------------------------------------|
| template_id | int | 是 | 模板id |
| name | string | 否 | 任务名 |
| creator | string | 是 | 创建者 |
| description | string | 否 | 描述 |
| constants | dict | 否 | 任务启动参数 |
| mock_data | dict | 否 | mock 数据,包含 nodes(mock 执行选中的节点) 和 outputs(mock 执行对应节点的 mock 数据,没有则表示不 mock) |
| 字段 | 类型 | 必选 | 描述 |
|-------------|--------|----|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| template_id | int | 是 | 模板id |
| name | string | 否 | 任务名 |
| creator | string | 是 | 创建者 |
| description | string | 否 | 描述 |
| constants | dict | 否 | 任务启动参数 |
| mock_data | dict | 否 | mock 数据,包含 nodes(mock 任务使用 mock 执行的节点),outputs(可选参数,mock 执行对应节点的节点输出),mock_data_ids(mock 执行对应节点使用的 mock 数据 id,如果 outputs 没有传参,则会自动将创建任务时对应的 mock 数据 作为 outputs) |

### 请求参数示例

Expand All @@ -38,6 +38,9 @@
"nd7927122ef6310eb309c2c8d3f70c23": {
"callback_data": "abc"
}
},
"mock_data_ids": {
"nd7927122ef6310eb309c2c8d3f70c23": 1
}
}
}
Expand Down
28 changes: 23 additions & 5 deletions bkflow/apigw/serializers/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from bkflow.constants import MAX_LEN_OF_TASK_NAME, USER_NAME_MAX_LENGTH
from bkflow.pipeline_web.parser.validator import validate_web_pipeline_tree
from bkflow.template.models import TemplateMockData
from bkflow.utils.strings import standardize_pipeline_node_name


Expand All @@ -35,11 +36,10 @@ class CreateTaskSerializer(serializers.Serializer):


class TaskMockDataSerializer(serializers.Serializer):
nodes = serializers.ListSerializer(
help_text=_("要 Mock 执行的节点 ID 列表"), child=serializers.CharField(), default=[]
)
outputs = serializers.JSONField(
help_text=_('节点 Mock 输出, 形如{"node_id": {"output1": "output_value1"}}'), default={}
nodes = serializers.ListSerializer(help_text=_("要 Mock 执行的节点 ID 列表"), child=serializers.CharField(), default=[])
outputs = serializers.JSONField(help_text=_('节点 Mock 输出, 形如{"node_id": {"output1": "output_value1"}}'), default={})
mock_data_ids = serializers.JSONField(
help_text=_("节点 Mock 数据,当 outputs 为空时会提取对应 mock_data_ids 设置 outputs,否则仅记录作用"), default={}
)


Expand All @@ -58,6 +58,24 @@ class CreateMockTaskWithPipelineTreeSerializer(CreateMockTaskBaseSerializer):
class CreateMockTaskWithTemplateIdSerializer(CreateMockTaskBaseSerializer):
template_id = serializers.IntegerField(help_text=_("模版ID"))

def validate(self, attrs):
if attrs["mock_data"]["mock_data_ids"] and not attrs["mock_data"]["outputs"]:
mock_data = TemplateMockData.objects.filter(
template_id=attrs["template_id"], id__in=list(attrs["mock_data"]["mock_data_ids"].values())
).values("id", "data")
mock_data = {item["id"]: item["data"] for item in mock_data}
outputs = {}
for node_id, mock_data_id in attrs["mock_data"]["mock_data_ids"].items():
if node_id not in attrs["mock_data"].get("nodes"):
continue
if mock_data_id not in mock_data:
raise serializers.ValidationError(
f"mock data of node {node_id} with mock_data_id {mock_data_id} not found"
)
outputs[node_id] = mock_data[mock_data_id].get("data", {})
attrs["mock_data"]["outputs"] = outputs
return attrs


class CreateTaskWithoutTemplateSerializer(serializers.Serializer):
name = serializers.CharField(help_text=_("任务名"), max_length=MAX_LEN_OF_TASK_NAME, required=False)
Expand Down
4 changes: 2 additions & 2 deletions bkflow/task/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class AutoRetryNodeStrategyAdmin(admin.ModelAdmin):

@admin.register(models.TaskMockData)
class TaskMockDataAdmin(admin.ModelAdmin):
list_display = ["id", "taskflow_id", "data"]
search_fields = ["taskflow_id"]
list_display = ["id", "taskflow_id", "mock_data_ids", "data"]
search_fields = ["taskflow_id", "mock_data_ids"]


admin.site.register(TaskOperationRecord, BaseOperateRecordAdmin)
18 changes: 18 additions & 0 deletions bkflow/task/migrations/0009_taskmockdata_mock_data_ids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.15 on 2024-09-14 08:21

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('task', '0008_alter_taskoperationrecord_instance_id'),
]

operations = [
migrations.AddField(
model_name='taskmockdata',
name='mock_data_ids',
field=models.JSONField(default=dict, verbose_name='task mock data ids'),
),
]
14 changes: 7 additions & 7 deletions bkflow/task/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ def create_instance(self, *args, **kwargs):
new_mock_data["outputs"] = {
act_mappings[node_id]: outputs for node_id, outputs in mock_data.get("outputs", {}).items()
}
TaskMockData.objects.create(taskflow_id=instance.id, data=new_mock_data)
TaskMockData.objects.create(
taskflow_id=instance.id, data=new_mock_data, mock_data_ids=mock_data.get("mock_data_ids", {})
)
# create auto retry strategy
arn_creator = AutoRetryNodeStrategyCreator(taskflow_id=instance.id, root_pipeline_id=instance.instance_id)
arn_creator.batch_create_strategy(pipeline_tree)
Expand Down Expand Up @@ -149,12 +151,8 @@ class TaskInstance(models.Model):
is_deleted = models.BooleanField("是否已经删除", default=False, help_text="表示当前实例是否删除")
is_expired = models.BooleanField("是否已经过期", default=False, help_text="运行时被定期清理即为过期")
snapshot_id = models.BigIntegerField(verbose_name="实例结构数据ID", null=True, blank=True, db_index=True)
execution_snapshot_id = models.BigIntegerField(
verbose_name="用于实例执行的结构数据ID", null=True, blank=True, db_index=True
)
tree_info_id = models.BigIntegerField(
verbose_name="提前计算好的一些流程结构数据ID", null=True, blank=True, db_index=True
)
execution_snapshot_id = models.BigIntegerField(verbose_name="用于实例执行的结构数据ID", null=True, blank=True, db_index=True)
tree_info_id = models.BigIntegerField(verbose_name="提前计算好的一些流程结构数据ID", null=True, blank=True, db_index=True)
extra_info = models.JSONField(verbose_name="额外信息", default=dict)

objects = TaskInstanceManager()
Expand Down Expand Up @@ -375,6 +373,7 @@ class TaskMockData(models.Model):
id = models.BigAutoField(verbose_name="ID", primary_key=True)
taskflow_id = models.BigIntegerField(verbose_name="taskflow id", db_index=True)
data = models.JSONField(verbose_name="task mock data")
mock_data_ids = models.JSONField(verbose_name="task mock data ids", default=dict)
create_time = models.DateTimeField("创建时间", auto_now_add=True, db_index=True)

class Meta:
Expand All @@ -386,5 +385,6 @@ def to_json(self):
"id": self.id,
"taskflow_id": self.taskflow_id,
"data": self.data,
"mock_data_ids": self.mock_data_ids,
"create_time": self.create_time,
}
Loading