package service import ( "context" "gcy_hpc_server/internal/model" "gcy_hpc_server/internal/store" "go.uber.org/zap" ) // ApplicationService handles parameter validation, script rendering, and job // submission for parameterized HPC applications. type ApplicationService struct { store *store.ApplicationStore jobSvc *JobService workDirBase string logger *zap.Logger taskSvc *TaskService } func NewApplicationService(store *store.ApplicationStore, jobSvc *JobService, workDirBase string, logger *zap.Logger, taskSvc ...*TaskService) *ApplicationService { var ts *TaskService if len(taskSvc) > 0 { ts = taskSvc[0] } return &ApplicationService{store: store, jobSvc: jobSvc, workDirBase: workDirBase, logger: logger, taskSvc: ts} } // ListApplications delegates to the store. func (s *ApplicationService) ListApplications(ctx context.Context, page, pageSize int) ([]model.Application, int, error) { return s.store.List(ctx, page, pageSize) } // CreateApplication delegates to the store. func (s *ApplicationService) CreateApplication(ctx context.Context, req *model.CreateApplicationRequest) (int64, error) { return s.store.Create(ctx, req) } // GetApplication delegates to the store. func (s *ApplicationService) GetApplication(ctx context.Context, id int64) (*model.Application, error) { return s.store.GetByID(ctx, id) } // UpdateApplication delegates to the store. func (s *ApplicationService) UpdateApplication(ctx context.Context, id int64, req *model.UpdateApplicationRequest) error { return s.store.Update(ctx, id, req) } // DeleteApplication delegates to the store. func (s *ApplicationService) DeleteApplication(ctx context.Context, id int64) error { return s.store.Delete(ctx, id) } // [已禁用] 前端已全部迁移到 POST /tasks 接口,此方法不再被调用。 /* // SubmitFromApplication orchestrates the full submission flow. // When TaskService is available, it delegates to ProcessTaskSync which creates // an hpc_tasks record and runs the full pipeline. Otherwise falls back to the // original direct implementation. func (s *ApplicationService) SubmitFromApplication(ctx context.Context, applicationID int64, values map[string]string) (*model.JobResponse, error) { // [已禁用] 旧的直接提交路径,已被 TaskService 管道取代。生产环境中 taskSvc 始终非 nil,此分支不会执行。 // if s.taskSvc != nil { req := &model.CreateTaskRequest{ AppID: applicationID, Values: values, InputFileIDs: nil, // old API has no file_ids concept TaskName: "", } return s.taskSvc.ProcessTaskSync(ctx, req) // } // // Fallback: original direct logic when TaskService not available // app, err := s.store.GetByID(ctx, applicationID) // if err != nil { // return nil, fmt.Errorf("get application: %w", err) // } // if app == nil { // return nil, fmt.Errorf("application %d not found", applicationID) // } // // var params []model.ParameterSchema // if len(app.Parameters) > 0 { // if err := json.Unmarshal(app.Parameters, ¶ms); err != nil { // return nil, fmt.Errorf("parse parameters: %w", err) // } // } // // if err := ValidateParams(params, values); err != nil { // return nil, err // } // // rendered := RenderScript(app.ScriptTemplate, params, values) // // workDir := "" // if s.workDirBase != "" { // safeName := SanitizeDirName(app.Name) // subDir := time.Now().Format("20060102_150405") + "_" + RandomSuffix(4) // workDir = filepath.Join(s.workDirBase, safeName, subDir) // if err := os.MkdirAll(workDir, 0777); err != nil { // return nil, fmt.Errorf("create work directory %s: %w", workDir, err) // } // // 绕过 umask,确保整条路径都有写权限 // for dir := workDir; dir != s.workDirBase; dir = filepath.Dir(dir) { // os.Chmod(dir, 0777) // } // os.Chmod(s.workDirBase, 0777) // } // // req := &model.SubmitJobRequest{Script: rendered, WorkDir: workDir} // return s.jobSvc.SubmitJob(ctx, req) } */