Skip to content

Commit 54d90da

Browse files
authored
Merge pull request #5390 from gchq/gh-5314-report-row-count
PR for #5314 - Send number of Rows returned to Report email template content
2 parents 6ee2174 + 9e982ca commit 54d90da

File tree

33 files changed

+1194
-489
lines changed

33 files changed

+1194
-489
lines changed

stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractScheduledQueryExecutor.java

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -230,32 +230,55 @@ private boolean executeIfScheduled(final T doc,
230230
private boolean execute(final T doc,
231231
final ExecutionSchedule executionSchedule,
232232
final TaskContext taskContext) {
233-
final ExecutionTracker currentTracker = executionScheduleDao.getTracker(executionSchedule).orElse(null);
233+
final ExecutionTracker currentTracker = executionScheduleDao.getTracker(executionSchedule)
234+
.orElse(null);
234235
final Schedule schedule = executionSchedule.getSchedule();
235236
final ScheduleBounds scheduleBounds = executionSchedule.getScheduleBounds();
236-
237237
// See if it is time to execute this query.
238238
final Instant executionTime = Instant.now();
239239
final Trigger trigger = TriggerFactory.create(schedule);
240240

241241
final Instant effectiveExecutionTime;
242242
if (currentTracker != null) {
243-
effectiveExecutionTime = Instant.ofEpochMilli(currentTracker.getNextEffectiveExecutionTimeMs());
243+
final Instant startTime = NullSafe.get(
244+
scheduleBounds,
245+
ScheduleBounds::getStartTimeMs,
246+
Instant::ofEpochMilli);
247+
final Instant trackerTime = Instant.ofEpochMilli(currentTracker.getNextEffectiveExecutionTimeMs());
248+
// User may have changed the start bound since the tracker was last updated, so if the new start
249+
// time is later, work from there
250+
effectiveExecutionTime = startTime != null && startTime.isAfter(trackerTime)
251+
? trigger.getNextExecutionTimeAfter(startTime)
252+
: trackerTime;
244253
} else {
245-
if (scheduleBounds != null && scheduleBounds.getStartTimeMs() != null) {
246-
effectiveExecutionTime = Instant.ofEpochMilli(scheduleBounds.getStartTimeMs());
247-
} else {
248-
effectiveExecutionTime = trigger.getNextExecutionTimeAfter(executionTime);
249-
}
254+
// No tracker so base the next eff time off now
255+
effectiveExecutionTime = NullSafe.getOrElseGet(
256+
scheduleBounds,
257+
ScheduleBounds::getStartTimeMs,
258+
Instant::ofEpochMilli,
259+
() -> trigger.getNextExecutionTimeAfter(executionTime));
250260
}
251261

252262
// Calculate end bounds.
253-
Instant endTime = Instant.MAX;
254-
if (scheduleBounds != null && scheduleBounds.getEndTimeMs() != null) {
255-
endTime = Instant.ofEpochMilli(scheduleBounds.getEndTimeMs());
256-
}
263+
final Instant endTime = NullSafe.getOrElse(
264+
scheduleBounds,
265+
ScheduleBounds::getEndTimeMs,
266+
Instant::ofEpochMilli,
267+
Instant.MAX);
268+
269+
LOGGER.debug("execute() - endTime: {}, executionTime: {}, " +
270+
"effectiveExecutionTime: {}, schedule: {}",
271+
endTime, executionTime, effectiveExecutionTime, schedule);
272+
273+
// bounds are inclusive
274+
if (effectiveExecutionTime != null
275+
&& !effectiveExecutionTime.isAfter(executionTime)
276+
&& !effectiveExecutionTime.isAfter(endTime)) {
277+
278+
LOGGER.debug("execute() - Executing - endTime: {}, executionTime: {}, " +
279+
"effectiveExecutionTime: {}, schedule: {}",
280+
endTime, executionTime, effectiveExecutionTime, schedule);
257281

258-
if (!effectiveExecutionTime.isAfter(executionTime) && !effectiveExecutionTime.isAfter(endTime)) {
259282
taskContext.info(() -> "Executing schedule '" +
260283
executionSchedule.getName() +
261284
"' with effective time: " +
@@ -273,6 +296,10 @@ private boolean execute(final T doc,
273296
effectiveExecutionTime,
274297
executionSchedule,
275298
currentTracker));
299+
} else {
300+
LOGGER.debug("execute() - Skipping execution - endTime: {}, executionTime: {}, " +
301+
"effectiveExecutionTime: {}, schedule: {}",
302+
endTime, executionTime, effectiveExecutionTime, schedule);
276303
}
277304
return false;
278305
}
@@ -368,5 +395,33 @@ private void info(final Supplier<String> messageSupplier) {
368395

369396
public record ExecutionResult(String status, String message) {
370397

398+
private static final ExecutionResult EMPTY = new ExecutionResult(null, null);
399+
400+
public static final String STATUS_COMPLETE = ExecutionHistory.STATUS_COMPLETE;
401+
public static final String STATUS_ERROR = ExecutionHistory.STATUS_ERROR;
402+
403+
public ExecutionResult {
404+
if (status != null) {
405+
if (!STATUS_COMPLETE.equals(status) && !STATUS_ERROR.equals(status)) {
406+
throw new IllegalArgumentException("Invalid status: " + status);
407+
}
408+
}
409+
if (message != null && status == null) {
410+
throw new IllegalArgumentException(LogUtil.message(
411+
"Can't have non-null message '{}' with no status", message));
412+
}
413+
}
414+
415+
public static ExecutionResult empty() {
416+
return EMPTY;
417+
}
418+
419+
public static ExecutionResult complete(final String message) {
420+
return new ExecutionResult(STATUS_COMPLETE, message);
421+
}
422+
423+
public static ExecutionResult error(final String message) {
424+
return new ExecutionResult(STATUS_ERROR, message);
425+
}
371426
}
372427
}

stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/EmailSender.java

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import jakarta.inject.Inject;
3131
import jakarta.inject.Provider;
3232
import jakarta.mail.Message.RecipientType;
33+
import org.jspecify.annotations.NonNull;
3334
import org.simplejavamail.api.email.AttachmentResource;
3435
import org.simplejavamail.api.email.Email;
3536
import org.simplejavamail.api.email.EmailPopulatingBuilder;
@@ -39,6 +40,7 @@
3940
import org.simplejavamail.mailer.MailerBuilder;
4041
import org.simplejavamail.mailer.internal.MailerRegularBuilderImpl;
4142

43+
import java.nio.file.Files;
4244
import java.nio.file.Path;
4345
import java.time.Instant;
4446
import java.util.ArrayList;
@@ -81,21 +83,60 @@ public void sendDetection(final NotificationEmailDestination emailDestination,
8183

8284
public void sendReport(final ReportDoc reportDoc,
8385
final NotificationEmailDestination emailDestination,
84-
final Path file,
86+
final ReportFile reportFile,
8587
final Instant executionTime,
8688
final Instant effectiveExecutionTime) {
89+
Objects.requireNonNull(reportDoc);
90+
Objects.requireNonNull(emailDestination);
91+
Objects.requireNonNull(reportFile);
92+
final Path file = reportFile.file();
93+
if (!Files.isRegularFile(file)) {
94+
throw new IllegalArgumentException(LogUtil.message("file '{}' does not exist or is not a regular file",
95+
file.toAbsolutePath().normalize()));
96+
}
97+
98+
// Set the context map for the templates to use
99+
final Map<String, Object> context = createTemplateContext(
100+
reportDoc,
101+
reportFile,
102+
executionTime,
103+
effectiveExecutionTime);
104+
105+
final EmailContent renderedEmail = ruleEmailTemplatingService.renderEmail(emailDestination, context);
106+
final List<AttachmentResource> attachmentResources = List.of(new AttachmentResource(
107+
file.getFileName().toString(),
108+
new FileDataSource(file.toFile())));
109+
if (LOGGER.isTraceEnabled()) {
110+
logContentsOfFile(file);
111+
}
112+
send(emailDestination, renderedEmail, reportDoc.getName(), attachmentResources);
113+
}
114+
115+
private static void logContentsOfFile(final Path file) {
116+
try {
117+
final String contents = Files.readString(file);
118+
LOGGER.trace("sendReport() - file: {}, contents:\n{}", file, contents);
119+
} catch (final Exception e) {
120+
// Swallow
121+
LOGGER.trace("Error logging file contents, file: {} - {}", file, LogUtil.exceptionMessage(e), e);
122+
}
123+
}
124+
125+
private static @NonNull Map<String, Object> createTemplateContext(final ReportDoc reportDoc,
126+
final ReportFile reportFile,
127+
final Instant executionTime,
128+
final Instant effectiveExecutionTime) {
129+
// Can't use Map.of() cos of null values
87130
final Map<String, Object> context = new HashMap<>();
88131
context.put("reportName", reportDoc.getName());
89132
context.put("description", reportDoc.getDescription());
90133
context.put("executionTime", DateUtil.createNormalDateTimeString(executionTime));
91134
context.put("effectiveExecutionTime", DateUtil.createNormalDateTimeString(effectiveExecutionTime));
92-
93-
ruleEmailTemplatingService.renderEmail(emailDestination, context);
94-
final EmailContent renderedEmail = ruleEmailTemplatingService.renderEmail(emailDestination, context);
95-
final List<AttachmentResource> attachmentResources = new ArrayList<>();
96-
attachmentResources.add(new AttachmentResource(file.getFileName().toString(),
97-
new FileDataSource(file.toFile())));
98-
send(emailDestination, renderedEmail, reportDoc.getName(), attachmentResources);
135+
context.put("rowCount", reportFile.rowCount());
136+
context.put("fileType", reportFile.fileType().name());
137+
context.put("fileName", reportFile.file().getFileName().toString());
138+
LOGGER.debug("createTemplateContext() - {}", context);
139+
return Collections.unmodifiableMap(context);
99140
}
100141

101142
private void send(final NotificationEmailDestination emailDestination,

0 commit comments

Comments
 (0)