|
@@ -2,6 +2,7 @@ package scheduler
|
|
|
|
|
|
import (
|
|
import (
|
|
"encoding/json"
|
|
"encoding/json"
|
|
|
|
+ "errors"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
"log"
|
|
"log"
|
|
"os"
|
|
"os"
|
|
@@ -16,13 +17,11 @@ import (
|
|
)
|
|
)
|
|
|
|
|
|
/*
|
|
/*
|
|
- ArOZ Emulated Crontab
|
|
|
|
|
|
+ ArozOS System Scheduler
|
|
author: tobychui
|
|
author: tobychui
|
|
|
|
|
|
- This is not actually a crontab but something similar that provide
|
|
|
|
- timered operations for executing commands in agi or bash in an interval
|
|
|
|
- bases
|
|
|
|
-
|
|
|
|
|
|
+ This module provide scheduling executable feature for ArozOS
|
|
|
|
+ Some feature was migrated from the v1.113 aecron module
|
|
*/
|
|
*/
|
|
|
|
|
|
type Job struct {
|
|
type Job struct {
|
|
@@ -32,7 +31,9 @@ type Job struct {
|
|
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
|
|
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
|
|
ExecutionInterval int64 //Execuation interval in seconds
|
|
BaseTime int64 //Exeuction basetime. The next interval is calculated using (current time - base time ) % execution interval
|
|
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)
|
|
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
|
|
}
|
|
}
|
|
|
|
|
|
type Scheduler struct {
|
|
type Scheduler struct {
|
|
@@ -65,7 +66,7 @@ func NewScheduler(userHandler *user.UserHandler, gateway *agi.Gateway, cronfile
|
|
}
|
|
}
|
|
|
|
|
|
//Create the ArOZ Emulated Crontask
|
|
//Create the ArOZ Emulated Crontask
|
|
- aecron := Scheduler{
|
|
|
|
|
|
+ thisScheduler := Scheduler{
|
|
jobs: jobs,
|
|
jobs: jobs,
|
|
userHandler: userHandler,
|
|
userHandler: userHandler,
|
|
gateway: gateway,
|
|
gateway: gateway,
|
|
@@ -81,13 +82,13 @@ func NewScheduler(userHandler *user.UserHandler, gateway *agi.Gateway, cronfile
|
|
for time.Now().Unix()%60 > 0 {
|
|
for time.Now().Unix()%60 > 0 {
|
|
time.Sleep(500 * time.Millisecond)
|
|
time.Sleep(500 * time.Millisecond)
|
|
}
|
|
}
|
|
- stopChannel := aecron.createTicker(1 * time.Minute)
|
|
|
|
- aecron.ticker = stopChannel
|
|
|
|
|
|
+ stopChannel := thisScheduler.createTicker(1 * time.Minute)
|
|
|
|
+ thisScheduler.ticker = stopChannel
|
|
log.Println("Emulated Crontab Started - Scheduling Tasks")
|
|
log.Println("Emulated Crontab Started - Scheduling Tasks")
|
|
}()
|
|
}()
|
|
|
|
|
|
//Return the crontask
|
|
//Return the crontask
|
|
- return &aecron, nil
|
|
|
|
|
|
+ return &thisScheduler, nil
|
|
}
|
|
}
|
|
|
|
|
|
//Load a list of jobs from file
|
|
//Load a list of jobs from file
|
|
@@ -108,6 +109,7 @@ func loadJobsFromFile(cronfile string) ([]*Job, error) {
|
|
//Convert the json objets to pointer for easy changing by other process
|
|
//Convert the json objets to pointer for easy changing by other process
|
|
jobsPointers := []*Job{}
|
|
jobsPointers := []*Job{}
|
|
for _, thisJob := range prevousJobs {
|
|
for _, thisJob := range prevousJobs {
|
|
|
|
+ thisJob.JobType = "file"
|
|
var newJobPointer Job = thisJob
|
|
var newJobPointer Job = thisJob
|
|
jobsPointers = append(jobsPointers, &newJobPointer)
|
|
jobsPointers = append(jobsPointers, &newJobPointer)
|
|
}
|
|
}
|
|
@@ -190,6 +192,52 @@ func (a *Scheduler) Close() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+//Add an job object to system scheduler
|
|
|
|
+func (a *Scheduler) AddJobToScheduler(job *Job) error {
|
|
|
|
+ if job.JobType == "" {
|
|
|
|
+ if job.ScriptFunc == nil && job.ScriptFile == "" {
|
|
|
|
+ return errors.New("Invalid job file or function")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if job.ScriptFunc != nil {
|
|
|
|
+ job.JobType = "function"
|
|
|
|
+ } else if job.ScriptFile != "" {
|
|
|
|
+ job.JobType = "file"
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ a.jobs = append(a.jobs, job)
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//Create a new scheduled function job in the scheduler
|
|
|
|
+func (a *Scheduler) CreateNewScheduledFunctionJob(name string, desc string, executionInterval int64, targetFunction func()) error {
|
|
|
|
+ if name == "" || desc == "" {
|
|
|
|
+ return errors.New("Name or description of a scheduled task cannot be empty")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if executionInterval < 60 {
|
|
|
|
+ return errors.New("The minimum execution interval is 60 seconds.")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //Create a new scehduled job
|
|
|
|
+ newJob := Job{
|
|
|
|
+ Name: name,
|
|
|
|
+ Creator: "system",
|
|
|
|
+ Description: desc,
|
|
|
|
+ Admin: true,
|
|
|
|
+ ExecutionInterval: executionInterval,
|
|
|
|
+ BaseTime: time.Now().Unix(),
|
|
|
|
+ JobType: "function",
|
|
|
|
+ ScriptFunc: targetFunction,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //Add the new job to scheduler
|
|
|
|
+ a.AddJobToScheduler(&newJob)
|
|
|
|
+
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
func (a *Scheduler) GetScheduledJobByName(name string) *Job {
|
|
func (a *Scheduler) GetScheduledJobByName(name string) *Job {
|
|
for _, thisJob := range a.jobs {
|
|
for _, thisJob := range a.jobs {
|
|
if thisJob.Name == name {
|
|
if thisJob.Name == name {
|