Skip to content

Commit

Permalink
HTM-1258: Allow storing only one task per search index
Browse files Browse the repository at this point in the history
  • Loading branch information
mprins committed Oct 23, 2024
1 parent 21c023e commit c85b851
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 1 deletion.
6 changes: 5 additions & 1 deletion build/qa/pmd-junit-ruleset.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ SPDX-License-Identifier: MIT
Junit ruleset. https://pmd.github.io/latest/pmd_userdocs_configuring_rules.html
</description>
<!-- if this fails check https://github.com/pmd/pmd/issues/2147 /-->
<rule ref="category/java/bestpractices.xml/JUnitTestsShouldIncludeAssert" />
<rule ref="category/java/bestpractices.xml/JUnitTestsShouldIncludeAssert">
<properties>
<property name="extraAssertMethodNames" value="assertThat" />
</properties>
</rule>
<rule ref="category/java/bestpractices.xml/SimplifiableTestAssertion" />
<rule ref="category/java/bestpractices.xml/JUnit5TestShouldBePackagePrivate" />
<rule ref="category/java/errorprone.xml/UnnecessaryBooleanAssertion" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@

import java.lang.invoke.MethodHandles;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -85,6 +88,7 @@ public void beforeSaveSearchIndexEventHandler(SearchIndex searchIndex) throws Sc
// this case can already be handled requesting a delete of the scheduled task instead
if (null != searchIndex.getSchedule()) {
if (null == searchIndex.getSchedule().getUuid()) {
validateNoTaskExistsForIndex(searchIndex);
// no task exists yet, create one
logger.info("Creating new task associated with search index: {}", searchIndex.getName());
TMJobDataMap jobDataMap =
Expand Down Expand Up @@ -122,4 +126,36 @@ public void beforeSaveSearchIndexEventHandler(SearchIndex searchIndex) throws Sc
}
}
}

/**
* Validate that no scheduled task exists for the given index.
*
* @param searchIndex the search index to validate for scheduling a task
* @throws SchedulerException if there is a task that is already associated with the given index
*/
private void validateNoTaskExistsForIndex(SearchIndex searchIndex) throws SchedulerException {
Optional<JobDataMap> jobDataMapOptional =
scheduler.getJobKeys(GroupMatcher.groupEquals(TaskType.INDEX.getValue())).stream()
.map(
jobKey -> {
try {
return scheduler.getJobDetail(jobKey).getJobDataMap();
} catch (SchedulerException e) {
logger.error("Error getting task detail", e);
return null;
}
})
.filter(Objects::nonNull)
.filter(
jobDataMap ->
searchIndex.getId().equals(jobDataMap.getLongValue(IndexTask.INDEX_KEY)))
.findFirst();

if (jobDataMapOptional.isPresent()) {
logger.warn("A scheduled task already exists for search index: {}", searchIndex.getName());
throw new SchedulerException(
"A scheduled task already exists for search index: '%s'"
.formatted(searchIndex.getName()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2024 B3Partners B.V.
*
* SPDX-License-Identifier: MIT
*/
package org.tailormap.api.repository.events;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assumptions.assumingThat;

import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.Issue;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.tailormap.api.annotation.PostgresIntegrationTest;
import org.tailormap.api.persistence.SearchIndex;
import org.tailormap.api.repository.SearchIndexRepository;

@PostgresIntegrationTest
class SearchIndexEventHandlerTest {
@Autowired SearchIndexEventHandler searchIndexEventHandler;
@Autowired SearchIndexRepository searchIndexRepository;

/**
* Test that a {@code SearchIndex} with a scheduled task that already exists cannot be saved with
* a new task through Spring Data REST.
*/
@Test
@Issue("HTM-1258")
void testBeforeSaveSearchIndexEventHandler() {

Check warning on line 32 in src/test/java/org/tailormap/api/repository/events/SearchIndexEventHandlerTest.java

View workflow job for this annotation

GitHub Actions / PMD

Best Practices JUnitTestsShouldIncludeAssert

JUnit tests should include assert() or fail()
SearchIndex existingSearchIndexWithSchedule = searchIndexRepository.findById(1L).orElse(null);

assumingThat(
null != existingSearchIndexWithSchedule
&& null != existingSearchIndexWithSchedule.getSchedule()
&& null != existingSearchIndexWithSchedule.getSchedule().getUuid(),
() -> {
final Exception actual =
assertThrows(
SchedulerException.class,
() -> {
existingSearchIndexWithSchedule.getSchedule().setUuid(null);
searchIndexEventHandler.beforeSaveSearchIndexEventHandler(
existingSearchIndexWithSchedule);
},
"Test did not invoke expected exception");

assertThat(actual.getMessage(), containsString("scheduled task already exists"));
});
}
}

0 comments on commit c85b851

Please sign in to comment.