-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
…nges to solr indexes
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
* Copyright (C) 2024 B3Partners B.V. | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
package nl.b3p.tailormap.api.repository.events; | ||
|
||
import java.io.IOException; | ||
import java.lang.invoke.MethodHandles; | ||
import nl.b3p.tailormap.api.geotools.featuresources.FeatureSourceFactoryHelper; | ||
import nl.b3p.tailormap.api.persistence.SearchIndex; | ||
import nl.b3p.tailormap.api.persistence.TMFeatureType; | ||
import nl.b3p.tailormap.api.repository.GeoServiceRepository; | ||
import nl.b3p.tailormap.api.repository.SearchIndexRepository; | ||
import nl.b3p.tailormap.api.solr.SolrHelper; | ||
import nl.b3p.tailormap.api.solr.SolrService; | ||
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; | ||
|
||
/** 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 30 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L29-L30
|
||
|
||
private final SearchIndexRepository searchIndexRepository; | ||
private final SolrService solrService; | ||
private final FeatureSourceFactoryHelper featureSourceFactoryHelper; | ||
private final GeoServiceRepository geoServiceRepository; | ||
|
||
public SolrTMFeatureTypeEventHandler( | ||
SearchIndexRepository searchIndexRepository, | ||
SolrService solrService, | ||
FeatureSourceFactoryHelper featureSourceFactoryHelper, | ||
GeoServiceRepository geoServiceRepository) { | ||
this.searchIndexRepository = searchIndexRepository; | ||
this.solrService = solrService; | ||
this.featureSourceFactoryHelper = featureSourceFactoryHelper; | ||
this.geoServiceRepository = geoServiceRepository; | ||
} | ||
Check warning on line 46 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L41-L46
|
||
|
||
/** | ||
* 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 55 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L55
|
||
// 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 59 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L59
|
||
} else { | ||
logger.debug("Updated TMFeatureType: {}", tmFeatureType); | ||
searchIndexRepository.findByFeatureTypeId(tmFeatureType.getId()).stream() | ||
.findAny() | ||
.ifPresent( | ||
Check warning on line 64 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L61-L64
|
||
searchIndex -> { | ||
logger.debug( | ||
Check warning on line 66 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L66
|
||
"Updating search index {} for feature type: {}", | ||
searchIndex.getName(), | ||
Check warning on line 68 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L68
|
||
searchIndex); | ||
|
||
try (SolrHelper solrHelper = | ||
new SolrHelper(solrService.getSolrClientForIndexing())) { | ||
solrHelper.addFeatureTypeIndex( | ||
Check warning on line 73 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L71-L73
|
||
searchIndex, tmFeatureType, featureSourceFactoryHelper); | ||
} catch (UnsupportedOperationException | ||
Check warning on line 75 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L75
|
||
| IOException | ||
| SolrServerException | ||
| SolrException e) { | ||
logger.error("Error re-indexing", e); | ||
searchIndex.setStatus(SearchIndex.Status.ERROR); | ||
searchIndexRepository.save(searchIndex); | ||
} | ||
}); | ||
Check warning on line 83 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L79-L83
|
||
} | ||
} | ||
Check warning on line 85 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L85
|
||
|
||
/** | ||
* 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 97 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L94-L97
|
||
searchIndex -> { | ||
logger.info( | ||
Check warning on line 99 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L99
|
||
"Deleting search index {} for feature type: {}", | ||
searchIndex.getName(), | ||
Check warning on line 101 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L101
|
||
searchIndex); | ||
|
||
try (SolrHelper solrHelper = new SolrHelper(solrService.getSolrClientForIndexing())) { | ||
solrHelper.clearIndexForLayer(searchIndex.getId()); | ||
searchIndexRepository.delete(searchIndex); | ||
Check warning on line 106 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L104-L106
|
||
// find layers that use this index in the layer settings and clear them | ||
geoServiceRepository | ||
.findByIndexId(searchIndex.getId()) | ||
.forEach( | ||
Check warning on line 110 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L108-L110
|
||
geoService -> | ||
geoService | ||
.getLayers() | ||
.forEach( | ||
Check warning on line 114 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L112-L114
|
||
layer -> { | ||
logger.debug( | ||
Check warning on line 116 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L116
|
||
"Checking layer {} for search index {}", | ||
layer.getName(), | ||
searchIndex.getName()); | ||
geoService | ||
.findSearchIndexForLayer(layer, searchIndexRepository) | ||
.ifPresent( | ||
Check warning on line 122 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L118-L122
|
||
searchIndex1 -> { | ||
if (searchIndex1 | ||
.getId() | ||
Check warning on line 125 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L124-L125
|
||
.equals(searchIndex.getId())) { | ||
logger.debug( | ||
Check warning on line 127 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L127
|
||
"Clearing search index for layer {}", | ||
layer.getName()); | ||
geoService | ||
.getLayerSettings(layer.getName()) | ||
.setSearchIndex(null); | ||
geoServiceRepository.save(geoService); | ||
Check warning on line 133 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L129-L133
|
||
} | ||
}); | ||
})); | ||
} catch (UnsupportedOperationException | ||
Check warning on line 137 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L135-L137
|
||
| IOException | ||
| SolrServerException | ||
| SolrException e) { | ||
logger.error("Error deleting index for {}", searchIndex, e); | ||
} | ||
}); | ||
} | ||
Check warning on line 144 in src/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java Codecov / codecov/patchsrc/main/java/nl/b3p/tailormap/api/repository/events/SolrTMFeatureTypeEventHandler.java#L141-L144
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright (C) 2024 B3Partners B.V. | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
package nl.b3p.tailormap.api.solr; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
import org.apache.solr.client.solrj.SolrClient; | ||
import org.apache.solr.client.solrj.impl.ConcurrentUpdateHttp2SolrClient; | ||
import org.apache.solr.client.solrj.impl.Http2SolrClient; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
public class SolrService { | ||
@Value("${tailormap-api.solr-url}") | ||
private String solrUrl; | ||
|
||
@Value("${tailormap-api.solr-core-name:tailormap}") | ||
private String solrCoreName; | ||
|
||
/** | ||
* Get a concurrent update Solr client for bulk operations. | ||
* | ||
* @return the Solr client | ||
*/ | ||
public SolrClient getSolrClientForIndexing() { | ||
return new ConcurrentUpdateHttp2SolrClient.Builder( | ||
solrUrl + solrCoreName, | ||
new Http2SolrClient.Builder() | ||
.withFollowRedirects(true) | ||
.withConnectionTimeout(10000, TimeUnit.MILLISECONDS) | ||
.withRequestTimeout(60000, TimeUnit.MILLISECONDS) | ||
.build()) | ||
.withQueueSize(SolrHelper.SOLR_BATCH_SIZE * 2) | ||
.withThreadCount(10) | ||
.build(); | ||
} | ||
|
||
/** | ||
* Get a Solr client for searching. | ||
* | ||
* @return the Solr client | ||
*/ | ||
public SolrClient getSolrClientForSearching() { | ||
return new Http2SolrClient.Builder(solrUrl + solrCoreName) | ||
.withConnectionTimeout(10, TimeUnit.SECONDS) | ||
.withFollowRedirects(true) | ||
.build(); | ||
} | ||
} |