1
2
3
4
5
6 package org.tailormap.api.repository.events;
7
8 import java.lang.invoke.MethodHandles;
9 import java.util.Map;
10 import java.util.Objects;
11 import java.util.Optional;
12 import java.util.UUID;
13 import org.quartz.JobDataMap;
14 import org.quartz.JobKey;
15 import org.quartz.Scheduler;
16 import org.quartz.SchedulerException;
17 import org.quartz.impl.matchers.GroupMatcher;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.data.rest.core.annotation.HandleAfterDelete;
22 import org.springframework.data.rest.core.annotation.HandleBeforeSave;
23 import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
24 import org.springframework.stereotype.Component;
25 import org.tailormap.api.persistence.SearchIndex;
26 import org.tailormap.api.scheduling.IndexTask;
27 import org.tailormap.api.scheduling.TMJobDataMap;
28 import org.tailormap.api.scheduling.Task;
29 import org.tailormap.api.scheduling.TaskManagerService;
30 import org.tailormap.api.scheduling.TaskType;
31
32
33
34
35
36 @Component
37 @RepositoryEventHandler
38 public class SearchIndexEventHandler {
39 private static final Logger logger =
40 LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
41
42 private final Scheduler scheduler;
43 private final TaskManagerService taskManagerService;
44
45 public SearchIndexEventHandler(@Autowired Scheduler scheduler, @Autowired TaskManagerService taskManagerService) {
46 this.scheduler = scheduler;
47 this.taskManagerService = taskManagerService;
48 }
49
50
51
52
53
54
55 @HandleAfterDelete
56 public void afterDeleteSearchIndexEventHandler(SearchIndex searchIndex) throws SchedulerException {
57 if (null != searchIndex.getSchedule()) {
58 JobKey jobKey = taskManagerService.getJobKey(
59 TaskType.INDEX, searchIndex.getSchedule().getUuid());
60
61 if (null != jobKey && scheduler.checkExists(jobKey)) {
62 logger.info(
63 "Deleting index task {} associated with search index: {}",
64 searchIndex.getSchedule().getUuid(),
65 searchIndex.getName());
66 boolean succes = scheduler.deleteJob(jobKey);
67 logger.info(
68 "Task {}:{} deletion {}",
69 jobKey.getGroup(),
70 jobKey.getName(),
71 (succes ? "succeeded" : "failed"));
72 }
73 }
74 }
75
76
77
78
79
80
81
82 @HandleBeforeSave
83 public void beforeSaveSearchIndexEventHandler(SearchIndex searchIndex) throws SchedulerException {
84
85
86
87 if (null != searchIndex.getSchedule()) {
88 if (null == searchIndex.getSchedule().getUuid()) {
89 validateNoTaskExistsForIndex(searchIndex);
90
91 logger.info("Creating new task associated with search index: {}", searchIndex.getName());
92 TMJobDataMap jobDataMap = new TMJobDataMap(Map.of(
93 Task.TYPE_KEY,
94 TaskType.INDEX,
95 Task.DESCRIPTION_KEY,
96 searchIndex.getSchedule().getDescription(),
97 IndexTask.INDEX_KEY,
98 searchIndex.getId().toString()));
99 if (null != searchIndex.getSchedule().getPriority()
100 && searchIndex.getSchedule().getPriority() > 0) {
101 jobDataMap.put(Task.PRIORITY_KEY, searchIndex.getSchedule().getPriority());
102 }
103 final UUID uuid = taskManagerService.createTask(
104 IndexTask.class, jobDataMap, searchIndex.getSchedule().getCronExpression());
105 searchIndex.getSchedule().setUuid(uuid);
106 } else {
107
108 logger.info(
109 "Updating task {} associated with search index: {}",
110 searchIndex.getSchedule().getUuid(),
111 searchIndex.getName());
112
113 JobKey jobKey = taskManagerService.getJobKey(
114 TaskType.INDEX, searchIndex.getSchedule().getUuid());
115 if (null != jobKey && scheduler.checkExists(jobKey)) {
116
117 JobDataMap jobDataMap = scheduler.getJobDetail(jobKey).getJobDataMap();
118 jobDataMap.put(
119 Task.DESCRIPTION_KEY, searchIndex.getSchedule().getDescription());
120 jobDataMap.put(
121 Task.CRON_EXPRESSION_KEY, searchIndex.getSchedule().getCronExpression());
122 if (null != searchIndex.getSchedule().getPriority()
123 && searchIndex.getSchedule().getPriority() > 0) {
124 jobDataMap.put(
125 Task.PRIORITY_KEY, searchIndex.getSchedule().getPriority());
126 }
127
128 taskManagerService.updateTask(jobKey, new TMJobDataMap(jobDataMap));
129 }
130 }
131 }
132 }
133
134
135
136
137
138
139
140 private void validateNoTaskExistsForIndex(SearchIndex searchIndex) throws SchedulerException {
141 Optional<JobDataMap> jobDataMapOptional =
142 scheduler.getJobKeys(GroupMatcher.groupEquals(TaskType.INDEX.getValue())).stream()
143 .map(jobKey -> {
144 try {
145 return scheduler.getJobDetail(jobKey).getJobDataMap();
146 } catch (SchedulerException e) {
147 logger.error("Error getting task detail", e);
148 return null;
149 }
150 })
151 .filter(Objects::nonNull)
152 .filter(jobDataMap -> searchIndex.getId().equals(jobDataMap.getLongValue(IndexTask.INDEX_KEY)))
153 .findFirst();
154
155 if (jobDataMapOptional.isPresent()) {
156 logger.warn("A scheduled task already exists for search index: {}", searchIndex.getName());
157 throw new SchedulerException(
158 "A scheduled task already exists for search index: '%s'".formatted(searchIndex.getName()));
159 }
160 }
161 }