1
2
3
4
5
6 package org.tailormap.api.scheduling;
7
8 import java.lang.invoke.MethodHandles;
9 import java.time.Instant;
10 import java.time.OffsetDateTime;
11 import java.time.ZoneId;
12 import java.util.Map;
13 import java.util.UUID;
14 import org.quartz.DisallowConcurrentExecution;
15 import org.quartz.InterruptableJob;
16 import org.quartz.JobDataMap;
17 import org.quartz.JobDetail;
18 import org.quartz.JobExecutionContext;
19 import org.quartz.JobExecutionException;
20 import org.quartz.PersistJobDataAfterExecution;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 import org.springframework.lang.NonNull;
24 import org.springframework.scheduling.quartz.QuartzJobBean;
25 import org.tailormap.api.admin.model.TaskProgressEvent;
26
27
28 @DisallowConcurrentExecution
29 @PersistJobDataAfterExecution
30 public class InterruptablePocTask extends QuartzJobBean implements Task, InterruptableJob {
31
32 private static final Logger logger =
33 LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
34
35 private boolean interrupted = false;
36
37 private String description;
38
39 @Override
40 public void interrupt() {
41 logger.info("Interrupting POC task");
42 interrupted = true;
43 }
44
45 @Override
46 protected void executeInternal(@NonNull JobExecutionContext context) throws JobExecutionException {
47
48 final JobDetail jobDetail = context.getJobDetail();
49
50
51 final JobDataMap mergedJobDataMap = context.getMergedJobDataMap();
52
53
54 final JobDataMap jobDataMap = jobDetail.getJobDataMap();
55
56 logger.debug(
57 "executing POC task {}:{}, details: {}",
58 jobDetail.getKey().getGroup(),
59 jobDetail.getKey().getName(),
60 mergedJobDataMap.getWrappedMap());
61
62 TaskProgressEvent progressEvent = new TaskProgressEvent()
63 .startedAt(OffsetDateTime.now(ZoneId.systemDefault()))
64 .type(getType().getValue())
65 .taskData(Map.of("jobKey", jobDetail.getKey().getName()))
66 .uuid(UUID.fromString(jobDetail.getKey().getName()));
67
68 try {
69 for (int i = 0; i < 110; i += 10) {
70
71 long workingTime = (long) (Math.random() * 5000);
72 logger.debug("Working for {} ms", workingTime);
73 Thread.sleep(workingTime);
74 logger.debug("Interruptable POC task is at {}%", i);
75 context.setResult("Interruptable POC task is at %d%%".formatted(i));
76 taskProgress(progressEvent.progress(i).total(100));
77 if (interrupted) {
78 logger.debug("Interruptable POC task interrupted at {}%", Instant.now());
79 jobDataMap.put(
80 Task.LAST_RESULT_KEY,
81 "Interruptable POC task interrupted after %d%% iterations".formatted(i));
82 jobDataMap.put(EXECUTION_FINISHED_KEY, null);
83 context.setResult("Interruptable POC task interrupted after %d%% iterations".formatted(i));
84
85 return;
86 }
87
88 if (i == 30) {
89 interrupt();
90 }
91 }
92 } catch (InterruptedException e) {
93 logger.error("Thread interrupted", e);
94 }
95
96 jobDataMap.put(EXECUTION_COUNT_KEY, (1 + (int) mergedJobDataMap.getOrDefault(EXECUTION_COUNT_KEY, 0)));
97 jobDataMap.put(EXECUTION_FINISHED_KEY, Instant.now());
98 jobDataMap.put(Task.LAST_RESULT_KEY, "Interruptable POC task executed successfully");
99 context.setResult("Interruptable POC task executed successfully");
100 }
101
102 @Override
103 public TaskType getType() {
104 return TaskType.INTERRUPTABLEPOC;
105 }
106
107 @Override
108 public String getDescription() {
109 return description;
110 }
111
112 @Override
113 public void setDescription(String description) {
114 this.description = description;
115 }
116 }