Skip to content

Commit ed0886b

Browse files
committed
#380 Quartz simulation
1 parent 015fd4f commit ed0886b

File tree

8 files changed

+57
-35
lines changed

8 files changed

+57
-35
lines changed

grails-app/controllers/au/org/ala/alerts/AdminController.groovy

+8-4
Original file line numberDiff line numberDiff line change
@@ -735,10 +735,13 @@ class AdminController {
735735
* Only send emails in Development environment
736736
* And NO database updates
737737
*/
738-
def triggerHourlyQueries() {
739-
log.info("****** Simulating hourly jobs, NO Database updates****** " + new Date())
740-
def logs = notificationService.execQueryForFrequency('hourly', Environment.current == Environment.DEVELOPMENT, true)
741-
log.info("****** End hourly job simulation ****** " + new Date())
738+
def triggerQueriesByFrequency(String frequency) {
739+
def allowedFrequencies = ['hourly', 'weekly', 'daily', 'monthly']
740+
def jobFrequency = (frequency in allowedFrequencies) ? frequency : 'daily'
741+
742+
log.info("****** Simulating ${jobFrequency} jobs, NO Database updates****** " + new Date())
743+
def logs = notificationService.execQueryForFrequency(jobFrequency, Environment.current == Environment.DEVELOPMENT, true)
744+
log.info("****** End ${jobFrequency} job simulation ****** " + new Date())
742745
render(logs.sort { [it.succeeded ? 1 : 0, it.hasChanged ? 0 : 1] } as JSON)
743746
}
744747

@@ -748,6 +751,7 @@ class AdminController {
748751
* Run a task to execute the query for a specific frequency
749752
*
750753
*/
754+
@Deprecated //Use triggerHourlyQueries instead
751755
def dryRunAllQueriesForFrequency(){
752756
def freq = params.frequency
753757
Frequency frequency = Frequency.findByName(freq)

grails-app/controllers/au/org/ala/alerts/NotificationController.groovy

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class NotificationController {
129129
// Since the previous and current results are loaded from database,
130130
// the diffService.getRecordChanges() should be called to get the new records
131131
queryResult.newRecords = diffService.getRecordChanges(queryResult)
132-
132+
queryResult.succeeded = true
133133
boolean hasChanged = queryResult.newRecords.size() > 0
134134
if (hasChanged != queryResult.hasChanged) {
135135
log.error("Warning: Calculated hasChanged flag is not consistent with result in database. Calculated: ${hasChanged}, in database: ${queryResult.hasChanged}")

grails-app/services/au/org/ala/alerts/DiffService.groovy

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class DiffService {
124124
log.warn "queryId: " + queryResult.query.id + ", queryResult:" + queryResult.id + " last or previous objects contains HTML and not JSON"
125125
}
126126
} catch (Exception ex) {
127-
log.error("queryId: ${queryResult.query.id}, Runtime error: ${ex.getMessage()}")
127+
log.error("Diff Exception: [${queryResult.query.id}, ${queryResult.query?.name}]: Runtime error: ${ex.getMessage()}")
128128
}
129129

130130
return records
@@ -312,7 +312,7 @@ class DiffService {
312312
ids1 = JsonPath.read(last, fullRecordJsonPath)
313313
ids2 = JsonPath.read(previous, fullRecordJsonPath)
314314
} catch (PathNotFoundException e){
315-
log.info("it's not an error. Result doesn't contain any records since the returned json does not contain any 'recordJsonPath', if result is empty.")
315+
log.debug("it's not an error. Result doesn't contain any records since the returned json does not contain any 'recordJsonPath', if result is empty.")
316316
}
317317

318318
// pull together the records that have been added

grails-app/services/au/org/ala/alerts/MyAnnotationService.groovy

+19-5
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,17 @@ class MyAnnotationService{
3939
try {
4040
oldRecordsMap = JsonPath.read(previous, recordJsonPath).collectEntries { [(it.uuid): it] }
4141
}catch (PathNotFoundException e){
42-
log.warn("Previous result is empty or doesn't have any records containing a field ${recordJsonPath} defined in recordJsonPath")
42+
log.debug("Previous result is empty or doesn't have any records containing a field ${recordJsonPath} defined in recordJsonPath")
4343
}
4444
try {
4545
curRecordsMap = JsonPath.read(last, recordJsonPath).collectEntries { [(it.uuid): it] }
4646
}catch (PathNotFoundException e){
47-
log.warn("Current result is empty or doesn't have any records containing a field ${recordJsonPath} defined in recordJsonPath")
47+
log.debug("Current result is empty or doesn't have any records containing a field ${recordJsonPath} defined in recordJsonPath")
4848
}
4949
// if an occurrence record doesn't exist in previous result (added) or has different verified_assertions than previous (changed).
50-
def records = curRecordsMap.findAll {
50+
51+
// NOTE: values of a linkedHashMap is immutable, so we need to create a new list if we will add new records after
52+
Collection records = curRecordsMap.findAll {
5153
def record = it.value
5254
// if the record has verified assertions and it is a list - some legacy records may have a String instead of a list
5355
if (!record.verified_assertions?.isEmpty() && record.verified_assertions instanceof List) {
@@ -67,11 +69,23 @@ class MyAnnotationService{
6769

6870
}.values()
6971

72+
// make a copy of the records list to make it mutable
73+
def mutableRecords = new ArrayList(records)
7074
//if an occurrence record exists in previous result but not in current, it means the annotation is deleted.
7175
//We need to add these records as a 'modified' record
72-
records.addAll(oldRecordsMap.findAll { !curRecordsMap.containsKey(it.value.uuid) }.values())
76+
//mutableRecords.addAll(oldRecordsMap.findAll { !curRecordsMap.containsKey(it.value.uuid) }.values())
77+
78+
def missingEntries = oldRecordsMap.findAll { entry ->
79+
def record = entry.value // Get the value from the map entry
80+
!curRecordsMap.containsKey(record.uuid) // Check if the uuid is missing in curRecordsMap
81+
}
82+
Collection missingRecords = missingEntries.values()
83+
if (missingRecords.size() > 0) {
84+
log.debug("Found ${missingRecords.size()} missing records: ${missingRecords.collect { it.uuid }}")
85+
mutableRecords.addAll(missingRecords)
86+
}
7387

74-
return records
88+
return mutableRecords
7589
}
7690

7791
/**

grails-app/services/au/org/ala/alerts/NotificationService.groovy

+4-7
Original file line numberDiff line numberDiff line change
@@ -102,22 +102,19 @@ class NotificationService {
102102
} finally {
103103
Date endTime = new Date()
104104
def duration = TimeCategory.minus(endTime, startTime)
105+
String msg = "${qr.succeeded ? (qr.hasChanged ? qr.newRecords.size() + ' new records found' : 'Completed - No new records') : 'Aborted'}. [${query.id}, ${query.name}, ${frequency.name}]. Time cost: ${duration}"
106+
qr.addLog(msg)
107+
log.info(msg)
105108

106109
if(!dryRun ){
107110
if (qr.succeeded) {
108-
String msg = "Completed [${query.id}, ${query.name}, ${frequency.name}]. Time cost: ${duration}"
109-
qr.addLog(msg)
110-
log.info(msg)
111-
112111
QueryResult.withTransaction {
113112
if (!qr.save(validate: true)) {
114113
qr.errors.allErrors.each {
115114
log.error(it)
116115
}
117116
}
118117
}
119-
} else {
120-
log.info("Aborted. [${query.id}, ${query.name}, ${frequency.name}]. Time cost: ${duration}")
121118
}
122119
}
123120
else {
@@ -563,7 +560,7 @@ class NotificationService {
563560
* @return logs for each query
564561
*/
565562
def execQueryForFrequency(String frequencyName, boolean sendEmails = true, boolean dryRun = false) {
566-
log.info("Checking frequency : ${frequencyName}, emails ${sendEmails} dryRun ${dryRun}")
563+
log.info("Checking frequency : ${frequencyName}, emails ${sendEmails}, dryRun ${dryRun}")
567564
def logs = []
568565
Date now = new Date()
569566
Frequency frequency = Frequency.findByName(frequencyName)

grails-app/views/admin/index.gsp

+22-7
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,19 @@
3535
View each alert type with counts for users</g:link> - View the list of all available custom and default alerts with user subscription count.</li>
3636

3737
<li><g:link controller="admin" action="deleteOrphanAlerts">Delete orphaned queries</g:link> - Remove queries no longer associated with Alert Notification/Subscription.</li>
38-
<li><g:link controller="admin" action="dryRunAllQueriesForFrequency" params="[frequency: 'daily']" target="_blank">Debug daily alerts</g:link> - Dry-run of daily alerts to determine if emails will be triggered on the next schedule. </li>
38+
%{-- <li><g:link controller="admin" action="dryRunAllQueriesForFrequency" params="[frequency: 'daily']" target="_blank">Debug daily alerts</g:link> - Dry-run of daily alerts to determine if emails will be triggered on the next schedule. </li>--}%
3939
<li class="admin"><a class="btn btn-info" href="${request.contextPath}/admin/query">Debug and Test</a> - For testers and developers</li>
40-
<li class="admin"><a class="btn btn-info" href="${g.createLink(controller: 'admin', action: 'triggerHourlyQueries')}" target="_blank">
41-
Simulating an Hourly Scheduler Job
42-
</a> Will NOT update the database, and emails will ONLY be sent in the development environment.</li>
40+
<li class="admin">
41+
Simulating a
42+
<select id="frequencySimulated" class="form-select">
43+
<option value="hourly">Hourly</option>
44+
<option value="daily" selected>Daily</option>
45+
<option value="weekly">Weekly</option>
46+
<option value="monthly">Monthly</option>
47+
</select>
48+
Scheduled Job <a class="btn btn-info" id="simulatedFrequencyLink" href="${g.createLink(controller: 'admin', action: 'triggerQueriesByFrequency', params: [frequency: 'daily'])}" target="_blank">Run</a>
49+
- Will NOT update the database, and emails will ONLY be sent in the Development environment.
50+
</li>
4351
</ul>
4452
<h4>Fix empty/invalid notification_token</h4>
4553
<ul>
@@ -87,9 +95,16 @@
8795
</plugin:isAvailable>
8896
</ul>
8997
</div>
90-
91-
92-
9398
</div>
99+
100+
<script>
101+
$(document).ready(function() {
102+
$('#frequencySimulated').change(function() {
103+
let selectedValue = $(this).val();
104+
let queryLink = $('#simulatedFrequencyLink');
105+
queryLink.attr('href', "${g.createLink(controller: 'admin', action: 'triggerQueriesByFrequency')}?frequency=" + selectedValue);
106+
});
107+
});
108+
</script>
94109
</body>
95110
</html>

grails-app/views/admin/query.gsp

-8
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,6 @@
4747

4848
</head>
4949
<body>
50-
<div>
51-
<div class="panel panel-default">
52-
<div class="panel-heading">Dry run tests. No DB updates, No emails sent </div>
53-
<div class="panel-body">
54-
<a class="btn btn-info" href = "/admin/dryRunAllQueriesForFrequency?frequency=daily" target="_blank">Dry run daily tasks</a>
55-
</div>
56-
</div>
57-
</div>
5850
<div>
5951
<ul class="nav nav-tabs" id="myTab" role="tablist">
6052
<g:each var="queryType" in="${queries.keySet()}" status="i">

grails-app/views/email/myAnnotations.gsp

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<g:each status="i" in="${records}" var="oc">
4141
<tr>
4242
<td style="padding: 20px;background-color: white;font-family: 'Roboto', sans-serif;font-size: 14px;line-height: 1.5;">
43-
<g:set var="occurrencelink" value="${query.baseUrlForUI}/occurrences/${oc.uuid}"></g:set>
43+
<g:set var="occurrencelink" value="${query.baseUrlForUI}/occurrences/${oc.uuid}#userAnnotationsList"></g:set>
4444
<g:set var="assertionlink" value="${query.baseUrl}/occurrences/${oc.uuid}/assertions"></g:set>
4545
<table style="width: 100%">
4646
<tr style="vertical-align: top;">

0 commit comments

Comments
 (0)