diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java index 73df5db..383cf7d 100644 --- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTask.java @@ -1,8 +1,13 @@ package com.my.graphiteDigesterBg.diframe; public interface DiTask { + // task status + enum TaskStatus { NEW, RUNNING, FINISHED, CANCELLED, WAITING, READY } + // get status + TaskStatus getStatus(); + // get UUID + String getUUID(); // set parameter void setParameter(Object parameter); - // run void run(); } diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java index fb8af7a..f01f2e1 100644 --- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskBase.java @@ -1,7 +1,12 @@ package com.my.graphiteDigesterBg.diframe; +import java.util.ArrayList; import java.util.List; import java.util.Map; abstract public class DiTaskBase implements DiTask { + // uuid + private final String uuid; + // status + private TaskStatus status; // parameter private Object parameter; // steps @@ -9,6 +14,29 @@ abstract public class DiTaskBase implements DiTask { // step index private Integer stepIndex; + // constructor + public DiTaskBase() { + this.uuid = java.util.UUID.randomUUID().toString(); + this.steps = new ArrayList<>(); + this.stepIndex = 0; + this.status = TaskStatus.NEW; + } + + // set status + protected void setStatus(TaskStatus status) { + this.status = status; + } + + @Override + public String getUUID() { + return this.uuid; + } + + @Override + public TaskStatus getStatus() { + return this.status; + } + @Override public void setParameter(Object parameter) { this.parameter = parameter; @@ -17,6 +45,6 @@ abstract public class DiTaskBase implements DiTask { // run @Override public void run() { - // do something + this.status = TaskStatus.FINISHED; } } diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskExecutor.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskExecutor.java index db125ad..016e19d 100644 --- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskExecutor.java +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/DiTaskExecutor.java @@ -1,6 +1,8 @@ package com.my.graphiteDigesterBg.diframe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; public class DiTaskExecutor implements Runnable { // logger public static final Logger LOG = LoggerFactory.getLogger(DiTaskExecutor.class); @@ -10,25 +12,26 @@ public class DiTaskExecutor implements Runnable { private final Object stopRequestLock; // stop request flag private boolean isStopRequested; + // task list + private final List taskList; // constructor public DiTaskExecutor(DiDevice device) { this.device = device; this.stopRequestLock = new Object(); this.isStopRequested = false; + this.taskList = new ArrayList<>(); } @Override public void run() { LOG.info("Task executor started"); while ( !this.isStopRequested ) { - LOG.info("Task executor running"); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - LOG.error("Task executor interrupted"); + DiTask task = this.findExecutableTask(); + if ( null == task ) { break; } + this.runTask(task); } LOG.info("Task executor stopped"); synchronized (this.stopRequestLock) { @@ -36,11 +39,58 @@ public class DiTaskExecutor implements Runnable { } } + // run task + private void runTask(DiTask task) { + task.run(); + if ( task.getStatus() == DiTask.TaskStatus.FINISHED ) { + LOG.info("[Task #{}] finished", task.getUUID()); + this.taskList.remove(task); + } + } + + // find executable task + private DiTask findExecutableTask() { + do { + for ( DiTask task : this.taskList ) { + // found ready task + if ( task.getStatus() == DiTask.TaskStatus.READY ) { + LOG.info("[Task #{}] ready", task.getUUID()); + return task; + } + + // found new task + if ( task.getStatus() == DiTask.TaskStatus.NEW ) { + LOG.info("[Task #{}] started", task.getUUID()); + return task; + } + } + + // wait for new task + synchronized ( this.taskList ) { + try { + LOG.info("waiting for executable task"); + this.taskList.wait(); + LOG.info("waiting for executable task waked up"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // stop requested + if ( this.isStopRequested ) { + return null; + } + } while ( true ); + } + // stop executor public void stop() { LOG.info("Task executor stop requested"); + this.isStopRequested = true; + synchronized ( this.taskList ) { + this.taskList.notifyAll(); + } synchronized (this.stopRequestLock) { - this.isStopRequested = true; try { this.stopRequestLock.wait(); } catch (InterruptedException e) { @@ -50,6 +100,15 @@ public class DiTaskExecutor implements Runnable { LOG.info("Task executor stop completed"); } + // append task + public void appendTask(DiTask task) { + LOG.info("[Task #{}] appended", task.getUUID()); + this.taskList.add(task); + synchronized ( this.taskList ) { + this.taskList.notifyAll(); + } + } + public void pause() {} public void resume() {} } diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiTask.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiTask.java index 8ad18a6..9c22de3 100644 --- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiTask.java +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/ApiTask.java @@ -1,4 +1,36 @@ package com.my.graphiteDigesterBg.diframe.api; -public class ApiTask { - public void append( String name, Object params ) {} +import com.my.graphiteDigesterBg.diframe.*; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseBody; +import java.util.Map; +@Controller +public class ApiTask extends DiApiControllerBase { + @Resource + private DiDevice device; + + /** + * append a task to task manager + * @param params task params + *
  • - name: task name
  • + *
  • - params: task params
  • + * @return response + */ + @ResponseBody + @PostMapping("/api/task/append") + public DiApiResponse append(@RequestBody Map params) { + DiTaskExecutor executor = this.device.getTaskManager().getExecutor(); + if ( null == executor ) { + return this.error("task executor is not running"); + } + + String name = (String)params.get("name"); + Object taskParams = params.get("parameter"); + DiTaskManager taskManager = this.device.getTaskManager(); + DiTask task = taskManager.generateTask(name, taskParams); + executor.appendTask(task); + return this.success(); + } } diff --git a/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java b/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java index 750a11a..ab60e61 100644 --- a/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java +++ b/src/src/main/java/com/my/graphiteDigesterBg/task/TaskDigestion.java @@ -6,5 +6,6 @@ public class TaskDigestion extends DiTaskBase { @Override public void run() { System.out.println("TaskDigestion.run()"); + this.setStatus(TaskStatus.FINISHED); } }