@@ -3,6 +3,7 @@ package hpc_runtime_service
33import (
44 "fmt"
55 "regexp"
6+ "strconv"
67 "strings"
78
89 "github.com/ovvesley/akoflow/pkg/server/config"
@@ -200,88 +201,102 @@ func (s *HPCRuntimeService) extractJobID(outputCommand string) (string, error) {
200201func (s * HPCRuntimeService ) VerifyActivitiesWasFinished (workflow workflow_entity.Workflow ) bool {
201202 config .App ().Logger .Infof ("WORKER: Verify activities was finished in HPCRuntime" )
202203
204+ finishedActivities := s .getFinishedActivities (workflow )
205+ if len (finishedActivities ) == 0 {
206+ return true
207+ }
208+
209+ syncNeeded := false
203210 for _ , activity := range workflow .Spec .Activities {
204- if activity .GetRuntimeId () == s .runtimeName {
205- s .handleVerifyActivityWasFinished (activity , workflow )
211+ if activity .GetRuntimeId () != s .runtimeName {
212+ continue
213+ }
214+
215+ if _ , ok := finishedActivities [activity .Id ]; ! ok {
216+ continue
217+ }
218+
219+ if s .handleVerifyActivityWasFinished (activity ) {
220+ syncNeeded = true
206221 }
207222 }
223+
224+ if syncNeeded {
225+ s .syncWorkflowVolumes (workflow )
226+ }
227+
208228 return true
209229}
210230
211- func (s * HPCRuntimeService ) handleVerifyActivityWasFinished (activity workflow_activity_entity.WorkflowActivities , wf workflow_entity.Workflow ) int {
212- println ("Verifying activity: " , activity .Name , " with id: " , activity .Id )
213-
214- wfaDatabase , _ := s .activityRepository .Find (activity .Id )
231+ func (s * HPCRuntimeService ) getFinishedActivities (workflow workflow_entity.Workflow ) map [int ]struct {} {
232+ finishedActivities := make (map [int ]struct {})
215233
216- if wfaDatabase .Status == activity_repository .StatusFinished {
217- return activity_repository .StatusFinished
234+ runtimeName := s .runtimeName
235+ if runtimeName == "" && len (workflow .GetRuntimeId ()) > 0 {
236+ runtimeName = workflow .GetRuntimeId ()[0 ]
218237 }
219238
220- if wfaDatabase . Status == activity_repository . StatusCreated {
221- return activity_repository . StatusCreated
239+ if runtimeName == "" {
240+ return finishedActivities
222241 }
223242
224- runtime , err := s .runtimeRepository .GetByName (activity .GetRuntimeId ())
225-
243+ runtime , err := s .runtimeRepository .GetByName (runtimeName )
226244 if err != nil {
227245 config .App ().Logger .Infof ("WORKER: Error getting runtime from database." )
228- return activity_repository . StatusRunning
246+ return finishedActivities
229247 }
230248
231- if wfaDatabase . GetProcId () == "" {
232- config . App (). Logger . Infof ( "WORKER: Activity %d has no process ID" , activity . Id )
233- return activity_repository . StatusRunning
249+ sharedMountPath := workflow . GetMountPath ()
250+ if sharedMountPath == "" {
251+ sharedMountPath = runtime . GetCurrentRuntimeMetadata ( "MOUNT_PATH" )
234252 }
235253
236- commandVerify := fmt .Sprintf ("cat %s/akoflow_finished_%d_%d.txt" , runtime .GetCurrentRuntimeMetadata ("MOUNT_PATH" ), wf .GetId (), activity .Id )
254+ commandVerify := fmt .Sprintf ("find %s -maxdepth 1 -type f -name 'akoflow_finished_%d_*.txt' -print" , sharedMountPath , workflow .GetId ())
255+ output , err := s .connectorHPCRuntime .SetRuntime (* runtime ).RunCommandWithOutputRemote (commandVerify )
256+ if err != nil {
257+ config .App ().Logger .Infof ("WORKER: Error listing finished activities for workflow %d" , workflow .GetId ())
258+ return finishedActivities
259+ }
237260
238- output , _ := s .connectorHPCRuntime .SetRuntime (* runtime ).RunCommandWithOutputRemote (commandVerify )
261+ re := regexp .MustCompile (fmt .Sprintf (`akoflow_finished_%d_(\d+)\.txt` , workflow .GetId ()))
262+ for _ , match := range re .FindAllStringSubmatch (output , - 1 ) {
263+ if len (match ) < 2 {
264+ continue
265+ }
239266
240- scontrolResponse , err := s .extractJobIsFinished (output )
267+ activityID , err := strconv .Atoi (strings .TrimSpace (match [1 ]))
268+ if err != nil {
269+ continue
270+ }
241271
242- if err != nil {
243- config .App ().Logger .Infof ("WORKER: Error extracting job ID %s" , strings .TrimSpace (wfaDatabase .GetProcId ()))
244- return activity_repository .StatusRunning
272+ finishedActivities [activityID ] = struct {}{}
245273 }
246274
247- if scontrolResponse .State == "COMPLETED" {
248- config .App ().Logger .Infof ("WORKER: Activity %d finished" , activity .Id )
249- s .syncWorkflowVolumes (wf )
250- _ = s .activityRepository .UpdateStatus (activity .Id , activity_repository .StatusFinished )
251- return activity_repository .StatusFinished
252- }
275+ return finishedActivities
276+ }
253277
254- if scontrolResponse .State == "FAILED" || scontrolResponse .State == "CANCELLED+" || scontrolResponse .State == "CANCELLED" || scontrolResponse .State == "DEADLINE" || scontrolResponse .State == "TIMEOUT" || scontrolResponse .State == "OUT_OF_MEM+" {
255- config .App ().Logger .Infof ("WORKER: Activity %d failed" , activity .Id )
256- s .syncWorkflowVolumes (wf )
257- _ = s .activityRepository .UpdateStatus (activity .Id , activity_repository .StatusFinished )
258- return activity_repository .StatusFinished
259- }
278+ func (s * HPCRuntimeService ) handleVerifyActivityWasFinished (activity workflow_activity_entity.WorkflowActivities ) bool {
279+ println ("Verifying activity: " , activity .Name , " with id: " , activity .Id )
260280
261- if scontrolResponse . State == "RUNNING" {
262- config . App (). Logger . Infof ( "WORKER: Activity %d running" , activity . Id )
263- _ = s . activityRepository . UpdateStatus ( activity . Id , activity_repository .StatusRunning )
264- return activity_repository . StatusRunning
281+ wfaDatabase , _ := s . activityRepository . Find ( activity . Id )
282+
283+ if wfaDatabase . Status == activity_repository .StatusFinished {
284+ return false
265285 }
266286
267- if scontrolResponse .State == "PENDING" {
268- config .App ().Logger .Infof ("WORKER: Activity %d pending" , activity .Id )
269- _ = s .activityRepository .UpdateStatus (activity .Id , activity_repository .StatusRunning )
270- return activity_repository .StatusRunning
287+ if wfaDatabase .Status == activity_repository .StatusCreated {
288+ return false
271289 }
272290
273- return activity_repository .StatusRunning
291+ if wfaDatabase .GetProcId () == "" {
292+ config .App ().Logger .Infof ("WORKER: Activity %d has no process ID" , activity .Id )
293+ return false
294+ }
274295
275- }
296+ config .App ().Logger .Infof ("WORKER: Activity %d finished" , activity .Id )
297+ _ = s .activityRepository .UpdateStatus (activity .Id , activity_repository .StatusFinished )
298+ return true
276299
277- type SaactResponse struct {
278- JobID string `json:"JobID"`
279- JobName string `json:"JobName"`
280- Partition string `json:"Partition"`
281- Account string `json:"Account"`
282- AllocCPUs string `json:"AllocCPUs"`
283- State string `json:"State"`
284- ExitCode string `json:"ExitCode"`
285300}
286301
287302func extractField (pattern , text string ) (string , error ) {
@@ -293,18 +308,6 @@ func extractField(pattern, text string) (string, error) {
293308 return match [1 ], nil
294309}
295310
296- func (s * HPCRuntimeService ) extractJobIsFinished (output string ) (SaactResponse , error ) {
297- // verify if output contains "AKOFLOW_JOB_FINISHED"
298- if ! strings .Contains (output , "AKOFLOW_JOB_FINISHED" ) {
299- return SaactResponse {}, fmt .Errorf ("job not finished" )
300- }
301-
302- return SaactResponse {
303- State : "COMPLETED" ,
304- }, nil
305-
306- }
307-
308311func (s * HPCRuntimeService ) HealthCheck (runtimeName string ) bool {
309312 config .App ().Logger .Infof ("WORKER: Health check HPCRuntime" )
310313
0 commit comments