Parcourir la source

Fixed bugs in scheduler creation function

TC pushbot 5 il y a 4 ans
Parent
commit
5d2708d1a9
3 fichiers modifiés avec 83 ajouts et 64 suppressions
  1. 3 3
      mod/filesystem/hybridBackup/hybridBackup.go
  2. 73 54
      mod/time/scheduler/scheduler.go
  3. 7 7
      storage.go

+ 3 - 3
mod/filesystem/hybridBackup/hybridBackup.go

@@ -20,7 +20,7 @@ import "log"
 
 */
 
-func HandleBackupProcess(backupConfig *BackupConfig) error {
-	log.Println(backupConfig)
-	return nil
+func HandleBackupProcess(backupConfig *BackupConfig) (string, error) {
+	log.Println(">>>>>> Running backup process: ", backupConfig)
+	return "Running backup process", nil
 }

+ 73 - 54
mod/time/scheduler/scheduler.go

@@ -25,15 +25,15 @@ import (
 */
 
 type Job struct {
-	Name              string //The name of this job
-	Creator           string //The creator of this job. When execute, this user permission will be used
-	Description       string //Job description, can be empty
-	Admin             bool   //If the creator has admin permission during the creation of this job. If this doesn't match with the runtime instance, this job wille be skipped
-	ExecutionInterval int64  //Execuation interval in seconds
-	BaseTime          int64  //Exeuction basetime. The next interval is calculated using (current time - base time ) % execution interval
-	JobType           string //Job type, accept {file/function}. If not set default to file
-	ScriptFile        string //The script file being called. Can be an agi script (.agi / .js) or shell script (.bat or .sh)
-	ScriptFunc        func() `json:"-"` //The target function to execute
+	Name              string                 //The name of this job
+	Creator           string                 //The creator of this job. When execute, this user permission will be used
+	Description       string                 //Job description, can be empty
+	Admin             bool                   //If the creator has admin permission during the creation of this job. If this doesn't match with the runtime instance, this job wille be skipped
+	ExecutionInterval int64                  //Execuation interval in seconds
+	BaseTime          int64                  //Exeuction basetime. The next interval is calculated using (current time - base time ) % execution interval
+	JobType           string                 //Job type, accept {file/function}. If not set default to file
+	ScriptFile        string                 //The script file being called. Can be an agi script (.agi / .js) or shell script (.bat or .sh)
+	ScriptFunc        func() (string, error) `json:"-"` //The target function to execute
 }
 
 type Scheduler struct {
@@ -122,58 +122,74 @@ func (a *Scheduler) createTicker(duration time.Duration) chan bool {
 	stop := make(chan bool, 1)
 
 	go func() {
-		defer log.Println("Aecron Stopped")
+		defer log.Println("Scheduler Stopped")
 		for {
 			select {
 			case <-ticker.C:
 				//Run jobs
 				for _, thisJob := range a.jobs {
+					log.Println((time.Now().Unix()-thisJob.BaseTime)%thisJob.ExecutionInterval, thisJob.Name)
 					if (time.Now().Unix()-thisJob.BaseTime)%thisJob.ExecutionInterval == 0 {
 						//Execute this job
-						scriptFile := thisJob.ScriptFile
-						if !fileExists(scriptFile) {
-							//This job no longer exists in the file system. Remove it
-							a.RemoveJobFromScheduleList(thisJob.Name)
-						}
-						clonedJobStructure := *thisJob
-						ext := filepath.Ext(scriptFile)
-						if ext == ".js" || ext == ".agi" {
-							//Run using AGI interface in go routine
-							go func(thisJob Job) {
-								userinfo, err := a.userHandler.GetUserInfoFromUsername(thisJob.Creator)
-								if err != nil {
-									//This user not exists. Skip this script
-									cronlog("[ERROR] User not exists: " + thisJob.Creator + ". Skipping scheduled job: " + thisJob.Name + ".")
-									return
-								}
-
-								//Run the script with this user scope
-								resp, err := a.gateway.ExecuteAGIScriptAsUser(thisJob.ScriptFile, userinfo)
-								if err != nil {
-									cronlog("[ERROR] " + thisJob.Name + " " + err.Error())
-								} else {
-									cronlog(thisJob.Name + " " + resp)
-								}
-							}(clonedJobStructure)
-
-						} else if ext == ".bat" || ext == ".sh" {
-							//Run as shell script
-							go func(thisJob Job) {
-								scriptPath := thisJob.ScriptFile
-								if runtime.GOOS == "windows" {
-									scriptPath = strings.ReplaceAll(filepath.ToSlash(scriptPath), "/", "\\")
-								}
-								cmd := exec.Command(scriptPath)
-								out, err := cmd.CombinedOutput()
-								if err != nil {
-									cronlog("[ERROR] " + thisJob.Name + " " + err.Error() + " => " + string(out))
-								}
-								cronlog(thisJob.Name + " " + string(out))
-							}(clonedJobStructure)
+						if thisJob.JobType == "function" {
+							//Execute the script function
+							returnvalue, err := thisJob.ScriptFunc()
+							if err != nil {
+								log.Println(`*Scheduler* Error occured when running task ` + thisJob.Name + ": " + err.Error())
+								cronlog("[ERROR]: " + err.Error())
+								return
+							}
+
+							//Execution suceed. Log the return value
+							cronlog(returnvalue)
 						} else {
-							//Unknown script file. Ignore this
-							log.Println("This extension is not yet supported: ", ext)
+							//This is requesting to execute a script file
+							scriptFile := thisJob.ScriptFile
+							if !fileExists(scriptFile) {
+								//This job no longer exists in the file system. Remove it
+								a.RemoveJobFromScheduleList(thisJob.Name)
+							}
+							clonedJobStructure := *thisJob
+							ext := filepath.Ext(scriptFile)
+							if ext == ".js" || ext == ".agi" {
+								//Run using AGI interface in go routine
+								go func(thisJob Job) {
+									userinfo, err := a.userHandler.GetUserInfoFromUsername(thisJob.Creator)
+									if err != nil {
+										//This user not exists. Skip this script
+										cronlog("[ERROR] User not exists: " + thisJob.Creator + ". Skipping scheduled job: " + thisJob.Name + ".")
+										return
+									}
+
+									//Run the script with this user scope
+									resp, err := a.gateway.ExecuteAGIScriptAsUser(thisJob.ScriptFile, userinfo)
+									if err != nil {
+										cronlog("[ERROR] " + thisJob.Name + " " + err.Error())
+									} else {
+										cronlog(thisJob.Name + " " + resp)
+									}
+								}(clonedJobStructure)
+
+							} else if ext == ".bat" || ext == ".sh" {
+								//Run as shell script
+								go func(thisJob Job) {
+									scriptPath := thisJob.ScriptFile
+									if runtime.GOOS == "windows" {
+										scriptPath = strings.ReplaceAll(filepath.ToSlash(scriptPath), "/", "\\")
+									}
+									cmd := exec.Command(scriptPath)
+									out, err := cmd.CombinedOutput()
+									if err != nil {
+										cronlog("[ERROR] " + thisJob.Name + " " + err.Error() + " => " + string(out))
+									}
+									cronlog(thisJob.Name + " " + string(out))
+								}(clonedJobStructure)
+							} else {
+								//Unknown script file. Ignore this
+								log.Println("This extension is not yet supported: ", ext)
+							}
 						}
+
 					}
 				}
 			case <-stop:
@@ -211,7 +227,7 @@ func (a *Scheduler) AddJobToScheduler(job *Job) error {
 }
 
 //Create a new scheduled function job in the scheduler
-func (a *Scheduler) CreateNewScheduledFunctionJob(name string, desc string, executionInterval int64, targetFunction func()) error {
+func (a *Scheduler) CreateNewScheduledFunctionJob(name string, desc string, executionInterval int64, targetFunction func() (string, error)) error {
 	if name == "" || desc == "" {
 		return errors.New("Name or description of a scheduled task cannot be empty")
 	}
@@ -220,6 +236,9 @@ func (a *Scheduler) CreateNewScheduledFunctionJob(name string, desc string, exec
 		return errors.New("The minimum execution interval is 60 seconds.")
 	}
 
+	//Get the cloest minute
+	baseTime := time.Now().Unix() - (time.Now().Unix() % 60)
+
 	//Create a new scehduled job
 	newJob := Job{
 		Name:              name,
@@ -227,7 +246,7 @@ func (a *Scheduler) CreateNewScheduledFunctionJob(name string, desc string, exec
 		Description:       desc,
 		Admin:             true,
 		ExecutionInterval: executionInterval,
-		BaseTime:          time.Now().Unix(),
+		BaseTime:          baseTime,
 		JobType:           "function",
 		ScriptFunc:        targetFunction,
 	}

+ 7 - 7
storage.go

@@ -112,19 +112,19 @@ func LoadBaseStoragePool() error {
 func FilesystemDaemonInit() {
 	for _, thisHandler := range fsHandlers {
 		if thisHandler.Hierarchy == "backup" {
+
 			//This is a backup drive. Generate it handler
 			backupConfig := thisHandler.HierarchyConfig.(hybridBackup.BackupConfig)
-			systemScheduler.CreateNewScheduledFunctionJob(thisHandler.UUID+"_backup-daemon",
+			systemScheduler.CreateNewScheduledFunctionJob("backup-daemon ["+thisHandler.UUID+"]",
 				"Backup daemon from "+backupConfig.ParentUID+":/ to "+backupConfig.DiskUID+":/",
-				60*5,
-				func() {
-					err := hybridBackup.HandleBackupProcess(&backupConfig)
-					if err != nil {
-						log.Println(err)
-					}
+				60,
+				func() (string, error) {
+					return hybridBackup.HandleBackupProcess(&backupConfig)
 				},
 			)
 		}
+
+		//Add other type of handler here
 	}
 }