You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

pagelisttasklogic.go 8.6 kB

3 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package xjlab
  2. import (
  3. "context"
  4. "time"
  5. jsoniter "github.com/json-iterator/go"
  6. "github.com/zeromicro/go-zero/core/logx"
  7. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
  8. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
  9. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/constants"
  10. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
  11. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils/timeutils"
  12. "gorm.io/gorm"
  13. )
  14. type PageListTaskLogic struct {
  15. logx.Logger
  16. ctx context.Context
  17. svcCtx *svc.ServiceContext
  18. }
  19. func NewPageListTaskLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PageListTaskLogic {
  20. return &PageListTaskLogic{
  21. Logger: logx.WithContext(ctx),
  22. ctx: ctx,
  23. svcCtx: svcCtx,
  24. }
  25. }
  26. type TaskResp struct {
  27. Id int64 `json:"id,omitempty,string" db:"id"` // id
  28. Name string `json:"name,omitempty" db:"name"` // 作业名称
  29. Description string `json:"description,omitempty" db:"description"` // 作业描述
  30. Status string `json:"status,omitempty" db:"status"` // 作业状态
  31. Strategy int64 `json:"strategy" db:"strategy"` // 策略
  32. SynergyStatus int64 `json:"synergyStatus" db:"synergy_status"` // 协同状态(0-未协同、1-已协同)
  33. CommitTime string `json:"commitTime,omitempty" db:"commit_time"` // 提交时间
  34. StartTime string `json:"startTime,omitempty" db:"start_time"` // 开始时间
  35. EndTime string `json:"endTime,omitempty" db:"end_time"` // 结束运行时间
  36. RunningTime int64 `json:"runningTime" db:"running_time"` // 已运行时间(单位秒)
  37. YamlString string `json:"yamlString,omitempty" db:"yaml_string"`
  38. Result string `json:"result,omitempty" db:"result"` // 作业结果
  39. DeletedAt string `json:"deletedAt,omitempty" gorm:"index" db:"deleted_at"`
  40. NsID string `json:"nsId,omitempty" db:"ns_id"`
  41. TenantId string `json:"tenantId,omitempty" db:"tenant_id"`
  42. CreatedTime string `json:"createdTime,omitempty" db:"created_time" gorm:"autoCreateTime"`
  43. UpdatedTime string `json:"updatedTime,omitempty" db:"updated_time"`
  44. AdapterTypeDict string `json:"adapterTypeDict" db:"adapter_type_dict" gorm:"adapter_type_dict"` //适配器类型(对应字典表的值
  45. TaskTypeDict string `json:"taskTypeDict" db:"task_type_dict" gorm:"task_type_dict"` //任务类型(对应字典表的值
  46. UserId int64 `json:"userId,omitempty" db:"user_id"`
  47. UserName string `json:"userName,omitempty" db:"user_name"`
  48. ClusterId string `json:"clusterId,omitempty" db:"cluster_id"`
  49. ClusterName string `json:"clusterName,omitempty" db:"cluster_name"`
  50. ResourceSpec string `json:"resourceSpec,omitempty" db:"resource_spec"`
  51. Card string `json:"card,omitempty" db:"card"`
  52. }
  53. // clusterInfo 集群信息结构体
  54. type clusterInfo struct {
  55. ClusterId string `json:"cluster_id"`
  56. ClusterName string `json:"cluster_name"`
  57. ResourceSpec string `json:"resource_spec"`
  58. Card string `json:"card"`
  59. }
  60. func (l *PageListTaskLogic) PageListTask(req *types.XJLABTaskReq) (*types.PageResult, error) {
  61. // 验证请求参数
  62. if err := l.validateRequest(req); err != nil {
  63. return nil, err
  64. }
  65. // 查询任务总数
  66. total, err := l.getTaskCount(req)
  67. if err != nil {
  68. return nil, err
  69. }
  70. // 查询任务列表
  71. tasks, err := l.getTaskList(req)
  72. if err != nil {
  73. return nil, err
  74. }
  75. // 异步更新任务状态
  76. l.updateTaskStatusAsync(tasks)
  77. // 处理任务响应数据
  78. taskResps := l.processTaskResponses(tasks)
  79. // 构建分页结果
  80. return &types.PageResult{
  81. List: &taskResps,
  82. PageSize: req.PageSize,
  83. PageNum: req.PageNum,
  84. Total: total,
  85. }, nil
  86. }
  87. // validateRequest 验证请求参数
  88. func (l *PageListTaskLogic) validateRequest(req *types.XJLABTaskReq) error {
  89. if req.PageSize <= 0 || req.PageNum <= 0 {
  90. return result.NewDefaultError("Invalid page size or page number")
  91. }
  92. return nil
  93. }
  94. // buildBaseQuery 构建基础查询条件
  95. func (l *PageListTaskLogic) buildBaseQuery(req *types.XJLABTaskReq) *gorm.DB {
  96. db := l.svcCtx.DbEngin.Model(&types.TaskModel{}).Table("task").Where("deleted_at is null")
  97. // 用户权限过滤
  98. if req.UserName != "" && req.UserName != "admin" {
  99. db = db.Where("user_name = ?", req.UserName)
  100. }
  101. // 任务名称模糊查询
  102. if req.Name != "" {
  103. db = db.Where("name LIKE ?", "%"+req.Name+"%")
  104. }
  105. // 计算类型筛选
  106. if req.AdapterTypeDict != "" {
  107. db = db.Where("adapter_type_dict = ?", req.AdapterTypeDict)
  108. }
  109. // 任务状态筛选
  110. if req.Status != "" {
  111. db = db.Where("status = ?", req.Status)
  112. }
  113. // 时间范围筛选
  114. if req.StartTime != "" && req.EndTime != "" {
  115. db = db.Where("created_time BETWEEN ? AND ?", req.StartTime, req.EndTime)
  116. }
  117. return db
  118. }
  119. // getTaskCount 获取任务总数
  120. func (l *PageListTaskLogic) getTaskCount(req *types.XJLABTaskReq) (int64, error) {
  121. var total int64
  122. db := l.buildBaseQuery(req)
  123. if err := db.Count(&total).Error; err != nil {
  124. return 0, result.NewDefaultError(err.Error())
  125. }
  126. return total, nil
  127. }
  128. // getTaskList 获取任务列表
  129. func (l *PageListTaskLogic) getTaskList(req *types.XJLABTaskReq) ([]*types.TaskModel, error) {
  130. var list []*types.TaskModel
  131. limit := req.PageSize
  132. offset := req.PageSize * (req.PageNum - 1)
  133. db := l.buildBaseQuery(req)
  134. if err := db.Limit(limit).Offset(offset).Order("created_time desc").Find(&list).Error; err != nil {
  135. return nil, result.NewDefaultError(err.Error())
  136. }
  137. return list, nil
  138. }
  139. // updateTaskStatusAsync 异步更新任务状态
  140. func (l *PageListTaskLogic) updateTaskStatusAsync(tasks []*types.TaskModel) {
  141. go l.svcCtx.Scheduler.AiService.St.UpdateTaskStatus(tasks)
  142. go l.svcCtx.Scheduler.AiService.St.UpdateAiTaskStatus(tasks)
  143. }
  144. // processTaskResponses 处理任务响应数据
  145. func (l *PageListTaskLogic) processTaskResponses(tasks []*types.TaskModel) []*TaskResp {
  146. taskResps := make([]*TaskResp, 0, len(tasks))
  147. for _, model := range tasks {
  148. // 计算运行时间
  149. model.RunningTime = l.calculateRunningTime(model.StartTime, model.EndTime)
  150. // 转换为响应结构体
  151. taskResp, err := l.convertToTaskResp(model)
  152. if err != nil {
  153. l.Errorf("Failed to convert task model: %v", err)
  154. continue
  155. }
  156. // 丰富任务详情
  157. enrichedTask := l.enrichTaskDetails(taskResp)
  158. taskResps = append(taskResps, &enrichedTask)
  159. }
  160. return taskResps
  161. }
  162. // convertToTaskResp 将TaskModel转换为TaskResp
  163. func (l *PageListTaskLogic) convertToTaskResp(model *types.TaskModel) (*TaskResp, error) {
  164. jsonData, err := jsoniter.Marshal(model)
  165. if err != nil {
  166. return nil, err
  167. }
  168. var taskResp TaskResp
  169. if err := jsoniter.Unmarshal(jsonData, &taskResp); err != nil {
  170. return nil, err
  171. }
  172. return &taskResp, nil
  173. }
  174. // calculateRunningTime 计算任务的运行时间
  175. func (l *PageListTaskLogic) calculateRunningTime(startTimeStr, endTimeStr string) int64 {
  176. if startTimeStr == "" {
  177. return 0
  178. }
  179. startTime := timeutils.TimeStringToGoTime(startTimeStr)
  180. // 如果没有结束时间,计算到当前时间
  181. if endTimeStr == "" {
  182. return int64(time.Since(startTime).Seconds())
  183. }
  184. endTime := timeutils.TimeStringToGoTime(endTimeStr)
  185. return int64(endTime.Sub(startTime).Seconds())
  186. }
  187. // enrichTaskDetails 丰富任务详情
  188. func (l *PageListTaskLogic) enrichTaskDetails(task *TaskResp) TaskResp {
  189. cluster := l.getClusterInfo(task.Id, task.AdapterTypeDict)
  190. task.ClusterId = cluster.ClusterId
  191. task.ClusterName = cluster.ClusterName
  192. task.ResourceSpec = cluster.ResourceSpec
  193. task.Card = cluster.Card
  194. return *task
  195. }
  196. // getClusterInfo 根据适配器类型获取集群信息
  197. func (l *PageListTaskLogic) getClusterInfo(taskId int64, adapterType string) clusterInfo {
  198. var cluster clusterInfo
  199. switch adapterType {
  200. case constants.AdapterTypeCloud:
  201. // 云计算任务
  202. l.svcCtx.DbEngin.Table("task_cloud").
  203. Where("task_id = ?", taskId).
  204. Select("cluster_id,cluster_name,resource_spec").
  205. Find(&cluster)
  206. case constants.AdapterTypeAI:
  207. // AI计算任务
  208. l.svcCtx.DbEngin.Table("task_ai").
  209. Where("task_id = ?", taskId).
  210. Select("cluster_id,cluster_name,resource_spec,card").
  211. Find(&cluster)
  212. // AI任务特殊处理:如果没有resource_spec,使用card字段
  213. if cluster.ResourceSpec == "" {
  214. cluster.ResourceSpec = cluster.Card
  215. }
  216. case constants.AdapterTypeHPC:
  217. // 高性能计算任务
  218. l.svcCtx.DbEngin.Table("task_hpc").
  219. Where("task_id = ?", taskId).
  220. Select("cluster_id,cluster_name,resource_spec").
  221. Find(&cluster)
  222. }
  223. return cluster
  224. }

PCM is positioned as Software stack over Cloud, aiming to build the standards and ecology of heterogeneous cloud collaboration for JCC in a non intrusive and autonomous peer-to-peer manner.