Skip to content

Commit

Permalink
WIP [HTM-1076][HTM-1077] TMFeatureType event handler to propagate cha…
Browse files Browse the repository at this point in the history
…nges to solr indexes

fixup after API changes in #876

move testcases and remove now useless test, use solr service inject

fix rebase issues
  • Loading branch information
mprins committed Nov 3, 2024
1 parent a707c7e commit a4fd212
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public class SolrAdminController {
private static final Logger logger =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final FeatureSourceFactoryHelper featureSourceFactoryHelper;

private final FeatureTypeRepository featureTypeRepository;
private final SearchIndexRepository searchIndexRepository;
private final SolrService solrService;
Expand All @@ -65,7 +64,7 @@ public SolrAdminController(
/**
* Ping solr.
*
* @return the response entity (ok or an error response)
* @return the response entity (OK or an error response)
*/
@Operation(summary = "Ping Solr", description = "Ping Solr to check if it is available")
@ApiResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
*/
package org.tailormap.api.repository;

import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.lang.NonNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.tailormap.api.persistence.Application;
Expand All @@ -21,4 +24,17 @@ public interface ApplicationRepository extends JpaRepository<Application, Long>
@Override
@NonNull
Optional<Application> findById(@NonNull Long aLong);

/**
* Find all applications that have a layer that is linked to a specific (Solr) index.
*
* @param indexId The index id to search for
*/
@NonNull
@PreAuthorize("permitAll()")
@Query(
value =
"select * from application app, lateral jsonb_path_query(app.settings, ('$.layerSettings.**{1}.searchIndexId ? (@ == '||:indexId||')')::jsonpath)",
nativeQuery = true)
List<Application> findByIndexId(@Param("indexId") @NonNull Long indexId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2024 B3Partners B.V.
*
* SPDX-License-Identifier: MIT
*/
package org.tailormap.api.repository.events;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.common.SolrException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.rest.core.annotation.HandleAfterDelete;
import org.springframework.data.rest.core.annotation.HandleBeforeSave;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import org.tailormap.api.geotools.featuresources.FeatureSourceFactoryHelper;
import org.tailormap.api.persistence.SearchIndex;
import org.tailormap.api.persistence.TMFeatureType;
import org.tailormap.api.persistence.json.AppLayerSettings;
import org.tailormap.api.repository.ApplicationRepository;
import org.tailormap.api.repository.SearchIndexRepository;
import org.tailormap.api.solr.SolrHelper;
import org.tailormap.api.solr.SolrService;

/** Event handler for Solr indexes when a {@code TMFeatureType} is updated or deleted. */
@RepositoryEventHandler
public class SolrTMFeatureTypeEventHandler {

private static final Logger logger =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

Check warning on line 31 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L30-L31

Added lines #L30 - L31 were not covered by tests

private final SearchIndexRepository searchIndexRepository;
private final SolrService solrService;
private final FeatureSourceFactoryHelper featureSourceFactoryHelper;
private final ApplicationRepository applicationRepository;

public SolrTMFeatureTypeEventHandler(
SearchIndexRepository searchIndexRepository,
SolrService solrService,
FeatureSourceFactoryHelper featureSourceFactoryHelper,
ApplicationRepository applicationRepository) {
this.searchIndexRepository = searchIndexRepository;
this.solrService = solrService;
this.featureSourceFactoryHelper = featureSourceFactoryHelper;
this.applicationRepository = applicationRepository;
}

Check warning on line 47 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L42-L47

Added lines #L42 - L47 were not covered by tests

/**
* Handle the update of a TMFeatureType.
*
* @param tmFeatureType the TMFeatureType to handle
*/
@HandleBeforeSave
public void handleTMFeatureTypeUpdate(TMFeatureType tmFeatureType) {
logger.debug("Handling TMFeatureType save event for: {}", tmFeatureType);

Check warning on line 56 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L56

Added line #L56 was not covered by tests
// determine if it is a new FT or an update
if (null == tmFeatureType.getId()) {
// do nothing as there is no index defined for a new feature type
logger.debug("New TMFeatureType: {}", tmFeatureType);

Check warning on line 60 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L60

Added line #L60 was not covered by tests
} else {
logger.debug("Updated TMFeatureType: {}", tmFeatureType);
searchIndexRepository.findByFeatureTypeId(tmFeatureType.getId()).stream()
.findAny()
.ifPresent(

Check warning on line 65 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L62-L65

Added lines #L62 - L65 were not covered by tests
searchIndex -> {
logger.debug(

Check warning on line 67 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L67

Added line #L67 was not covered by tests
"Updating search index {} for feature type: {}",
searchIndex.getName(),

Check warning on line 69 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L69

Added line #L69 was not covered by tests
searchIndex);

try (SolrHelper solrHelper =
new SolrHelper(solrService.getSolrClientForIndexing())) {
solrHelper.addFeatureTypeIndex(

Check warning on line 74 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L72-L74

Added lines #L72 - L74 were not covered by tests
searchIndex,
tmFeatureType,
featureSourceFactoryHelper,
searchIndexRepository);
} catch (UnsupportedOperationException

Check warning on line 79 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L79

Added line #L79 was not covered by tests
| IOException
| SolrServerException
| SolrException e) {
logger.error("Error re-indexing", e);
searchIndex.setStatus(SearchIndex.Status.ERROR);
searchIndexRepository.save(searchIndex);
}
});

Check warning on line 87 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L83-L87

Added lines #L83 - L87 were not covered by tests
}
}

Check warning on line 89 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L89

Added line #L89 was not covered by tests

/**
* Handle the deletion of a TMFeatureType.
*
* @param tmFeatureType the TMFeatureType to handle
*/
@HandleAfterDelete
public void handleTMFeatureTypeDeleteForSolr(TMFeatureType tmFeatureType) {
logger.debug("Handling TMFeatureType delete event for: {}", tmFeatureType);
searchIndexRepository.findByFeatureTypeId(tmFeatureType.getId()).stream()
.findAny()
.ifPresent(

Check warning on line 101 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L98-L101

Added lines #L98 - L101 were not covered by tests
searchIndex -> {
logger.info(

Check warning on line 103 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L103

Added line #L103 was not covered by tests
"Deleting search index {} for feature type: {}",
searchIndex.getName(),

Check warning on line 105 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L105

Added line #L105 was not covered by tests
searchIndex);

try (SolrHelper solrHelper = new SolrHelper(solrService.getSolrClientForIndexing())) {
solrHelper.clearIndexForLayer(searchIndex.getId());
searchIndexRepository.delete(searchIndex);

Check warning on line 110 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L108-L110

Added lines #L108 - L110 were not covered by tests
// find any application layers that use this index clear the index from them
applicationRepository
.findByIndexId(searchIndex.getId())
.forEach(

Check warning on line 114 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L112-L114

Added lines #L112 - L114 were not covered by tests
application -> {
application
.getAllAppTreeLayerNode()
.forEach(

Check warning on line 118 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L116-L118

Added lines #L116 - L118 were not covered by tests
appTreeLayerNode -> {
AppLayerSettings appLayerSettings =
application.getAppLayerSettings(appTreeLayerNode);

Check warning on line 121 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L120-L121

Added lines #L120 - L121 were not covered by tests
if (null != appLayerSettings.getSearchIndexId()
&& appLayerSettings
.getSearchIndexId()

Check warning on line 124 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L124

Added line #L124 was not covered by tests
.equals(searchIndex.getId())) {
appLayerSettings.setSearchIndexId(null);

Check warning on line 126 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L126

Added line #L126 was not covered by tests
}
});
applicationRepository.save(application);
});
} catch (UnsupportedOperationException

Check warning on line 131 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L128-L131

Added lines #L128 - L131 were not covered by tests
| IOException
| SolrServerException
| SolrException e) {
logger.error("Error deleting index for {}", searchIndex, e);
}
});
}

Check warning on line 138 in src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L135-L138

Added lines #L135 - L138 were not covered by tests
}
2 changes: 1 addition & 1 deletion src/main/java/org/tailormap/api/solr/SolrHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class SolrHelper implements AutoCloseable, Constants {
/**
* Constructor
*
* @param solrClient the Solr client, this will be closed when this class is closed
* @param solrClient the Solr client, this client will be closed when this class is closed.
*/
public SolrHelper(@NotNull SolrClient solrClient) {
this.solrClient = solrClient;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.tailormap.api.annotation.PostgresIntegrationTest;
Expand All @@ -30,4 +32,17 @@ void should_not_find_application_by_nonexistent_name() {
Application a = applicationRepository.findByName("does-not-exist");
assertNull(a);
}

@Test
void it_should_find_application_using_findByIndexId_with_valid_ID() {
final Application application = applicationRepository.findByIndexId(2L).get(0);
assertNotNull(application, "application should not be null");
assertEquals("default", application.getName(), "application name is incorrect");
}

@Test
void it_should_not_find_applications_findByIndexId_with_invalid_ID() {
final List<Application> applications = applicationRepository.findByIndexId(-2L);
assertTrue(applications.isEmpty(), "applications should be empty");
}
}

0 comments on commit a4fd212

Please sign in to comment.