Skip to content

Commit

Permalink
Merge branch 'main' into fix/use-doesNotHaveJsonPath-instead-of-doesN…
Browse files Browse the repository at this point in the history
…otExist
  • Loading branch information
matthijsln committed Dec 16, 2024
2 parents 55e203f + 652e97c commit 570fd4d
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 57 deletions.
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SPDX-License-Identifier: MIT
</parent>
<groupId>org.tailormap</groupId>
<artifactId>tailormap-api</artifactId>
<version>11.4.4-SNAPSHOT</version>
<version>11.4.5-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Tailormap API</name>
<description>Tailormap API provides the backend for Tailormap</description>
Expand Down Expand Up @@ -63,7 +63,7 @@ SPDX-License-Identifier: MIT
<scm>
<connection>scm:git:[email protected]:Tailormap/tailormap-api.git</connection>
<developerConnection>scm:git:[email protected]:Tailormap/tailormap-api.git</developerConnection>
<tag>tailormap-api-11.4.0</tag>
<tag>tailormap-api-11.4.4</tag>
<url>https://github.com/Tailormap/tailormap-api/</url>
</scm>
<issueManagement>
Expand Down Expand Up @@ -99,7 +99,7 @@ SPDX-License-Identifier: MIT
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.release>${java.version}</maven.compiler.release>
<maven-compiler-plugin.version>3.12.1</maven-compiler-plugin.version>
<project.build.outputTimestamp>2024-11-29T15:05:44Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2024-12-13T12:39:10Z</project.build.outputTimestamp>
<geotools.version>32.1</geotools.version>
<jts.version>1.20.0</jts.version>
<okhttp.version>5.0.0-alpha.14</okhttp.version>
Expand Down Expand Up @@ -155,7 +155,7 @@ SPDX-License-Identifier: MIT
<modernizer-maven-plugin.version>2.9.0</modernizer-maven-plugin.version>
<maven-fluido-skin.version>2.0.1</maven-fluido-skin.version>
<swagger-ui.version>5.18.2</swagger-ui.version>
<sentry.version>7.18.1</sentry.version>
<sentry.version>7.19.0</sentry.version>
<errorProne.version>2.36.0</errorProne.version>
<errorProneFlags>-XepDisableWarningsInGeneratedCode</errorProneFlags>
<errorProneExcludePaths>${project.build.directory}/generated-sources/.*</errorProneExcludePaths>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ private void createCatalogTestData() throws Exception {
.setId("at-basemap")
.setProtocol(WMTS)
.setTitle("basemap.at")
.setUrl("https://basemap.at/wmts/1.0.0/WMTSCapabilities.xml")
.setUrl("https://mapsneu.wien.gv.at/basemapneu/1.0.0/WMTSCapabilities.xml")
.setAuthorizationRules(ruleAnonymousRead)
.setPublished(true)
.setSettings(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import org.tailormap.api.admin.model.SearchIndexSummary;
import org.tailormap.api.persistence.SearchIndex;
import org.tailormap.api.persistence.TMFeatureSource;
import org.tailormap.api.persistence.TMFeatureType;
Expand Down Expand Up @@ -291,7 +292,9 @@ private SearchIndex validateInputAndFindIndex(Long searchIndexId) {

if (TMFeatureSource.Protocol.WFS.equals(indexingFT.getFeatureSource().getProtocol())) {
// the search index should not exist for WFS feature types, but test just in case
searchIndex.setStatus(SearchIndex.Status.ERROR).setComment("WFS indexing not supported");
searchIndex
.setStatus(SearchIndex.Status.ERROR)
.setSummary(new SearchIndexSummary().errorMessage("WFS indexing not supported"));
throw new ResponseStatusException(
HttpStatus.BAD_REQUEST, "Layer does not have valid feature type for indexing");
}
Expand Down Expand Up @@ -336,7 +339,7 @@ public ResponseEntity<?> clearIndex(@PathVariable Long searchIndexId) {
searchIndex
.setLastIndexed(null)
.setStatus(SearchIndex.Status.INITIAL)
.setComment("Index cleared");
.setSummary(new SearchIndexSummary().total(0));
searchIndexRepository.save(searchIndex);
} catch (IOException | SolrServerException | NoSuchElementException e) {
logger.warn("Error clearing index", e);
Expand Down
26 changes: 15 additions & 11 deletions src/main/java/org/tailormap/api/persistence/SearchIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.List;
import org.hibernate.annotations.Type;
import org.springframework.format.annotation.DateTimeFormat;
import org.tailormap.api.admin.model.SearchIndexSummary;
import org.tailormap.api.admin.model.TaskSchedule;
import org.tailormap.api.persistence.listener.EntityEventPublisher;

Expand Down Expand Up @@ -53,8 +54,11 @@ public class SearchIndex implements Serializable {
@Valid
private List<String> searchDisplayFieldsUsed = new ArrayList<>();

@Column(columnDefinition = "text")
private String comment;
@JsonProperty("summary")
@Type(value = io.hypersistence.utils.hibernate.type.json.JsonBinaryType.class)
@Column(columnDefinition = "jsonb")
@Valid
private SearchIndexSummary summary;

/** Date and time of last index creation. */
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
Expand Down Expand Up @@ -118,15 +122,6 @@ public SearchIndex setSearchDisplayFieldsUsed(List<String> searchDisplayFieldsUs
return this;
}

public String getComment() {
return comment;
}

public SearchIndex setComment(String comment) {
this.comment = comment;
return this;
}

public OffsetDateTime getLastIndexed() {
return lastIndexed;
}
Expand Down Expand Up @@ -154,6 +149,15 @@ public SearchIndex setSchedule(@Valid TaskSchedule schedule) {
return this;
}

public SearchIndexSummary getSummary() {
return summary;
}

public SearchIndex setSummary(SearchIndexSummary summary) {
this.summary = summary;
return this;
}

public enum Status {
INITIAL("initial"),
INDEXING("indexing"),
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/org/tailormap/api/scheduling/IndexTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.NonNull;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.tailormap.api.admin.model.SearchIndexSummary;
import org.tailormap.api.admin.model.ServerSentEvent;
import org.tailormap.api.admin.model.TaskProgressEvent;
import org.tailormap.api.geotools.featuresources.FeatureSourceFactoryHelper;
Expand Down Expand Up @@ -108,8 +109,7 @@ protected void executeInternal(@NonNull JobExecutionContext context)
.withBatchSize(solrBatchSize)
.withGeometryValidationRule(solrGeometryValidationRule)) {

searchIndex.setStatus(SearchIndex.Status.INDEXING);
searchIndex = searchIndexRepository.save(searchIndex);
searchIndex = searchIndexRepository.save(searchIndex.setStatus(SearchIndex.Status.INDEXING));

searchIndex =
solrHelper.addFeatureTypeIndex(
Expand All @@ -119,21 +119,22 @@ protected void executeInternal(@NonNull JobExecutionContext context)
searchIndexRepository,
this::taskProgress,
UUID.fromString(context.getTrigger().getJobKey().getName()));
searchIndex = searchIndex.setStatus(SearchIndex.Status.INDEXED);
searchIndexRepository.save(searchIndex);
searchIndex = searchIndexRepository.save(searchIndex.setStatus(SearchIndex.Status.INDEXED));
persistedJobData.put(
"executions", (1 + (int) context.getMergedJobDataMap().getOrDefault("executions", 0)));
persistedJobData.put("lastExecutionFinished", Instant.now());
persistedJobData.put(Task.LAST_RESULT_KEY, "Index task executed successfully");
context.setResult("Index task executed successfully");
} catch (UnsupportedOperationException | IOException | SolrServerException | SolrException e) {
logger.error("Error indexing", e);
searchIndex.setStatus(SearchIndex.Status.ERROR).setComment(e.getMessage());
persistedJobData.put("lastExecutionFinished", null);
persistedJobData.put(
Task.LAST_RESULT_KEY,
"Index task failed with " + e.getMessage() + ". Check logs for details");
searchIndexRepository.save(searchIndex);
searchIndexRepository.save(
searchIndex
.setStatus(SearchIndex.Status.ERROR)
.setSummary(new SearchIndexSummary().errorMessage(e.getMessage())));
context.setResult("Error indexing. Check logs for details.");
throw new JobExecutionException("Error indexing", e);
}
Expand Down
44 changes: 20 additions & 24 deletions src/main/java/org/tailormap/api/solr/SolrHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import jakarta.validation.constraints.Positive;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.time.OffsetDateTime;
Expand Down Expand Up @@ -43,6 +44,7 @@
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.tailormap.api.admin.model.SearchIndexSummary;
import org.tailormap.api.admin.model.TaskProgressEvent;
import org.tailormap.api.geotools.featuresources.FeatureSourceFactoryHelper;
import org.tailormap.api.geotools.processing.GeometryProcessor;
Expand Down Expand Up @@ -183,9 +185,7 @@ public SearchIndex addFeatureTypeIndex(
throws IOException, SolrServerException {
// use a dummy/logging listener when not given
Consumer<TaskProgressEvent> progressListener =
(event) -> {
logger.debug("Progress event: {}", event);
};
(event) -> logger.debug("Progress event: {}", event);

return this.addFeatureTypeIndex(
searchIndex,
Expand Down Expand Up @@ -234,13 +234,16 @@ public SearchIndex addFeatureTypeIndex(
taskUuid = searchIndex.getSchedule().getUuid();
}

SearchIndexSummary summary =
new SearchIndexSummary().startedAt(startedAtOffset).total(0).duration(0.0);

if (null == searchIndex.getSearchFieldsUsed()) {
logger.warn(
"No search fields configured for search index: {}, bailing out.", searchIndex.getName());
return searchIndexRepository.save(
searchIndex
.setStatus(SearchIndex.Status.ERROR)
.setComment("No search fields configured"));
.setSummary(summary.errorMessage("No search fields configured")));
}

progressListener.accept(
Expand All @@ -267,7 +270,7 @@ public SearchIndex addFeatureTypeIndex(
return searchIndexRepository.save(
searchIndex
.setStatus(SearchIndex.Status.ERROR)
.setComment("No search fields configured"));
.setSummary(summary.errorMessage("No search fields configured")));
}

// add search and display properties to query
Expand Down Expand Up @@ -397,28 +400,21 @@ public SearchIndex addFeatureTypeIndex(
logger.warn(
"{} features were skipped because no search or display values were found.",
indexSkippedCounter);
searchIndex =
searchIndex.setComment(
"Indexed %s features in %s.%s seconds, started at %s. %s features were skipped because no search or display values were found."
.formatted(
total,
processTime.getSeconds(),
processTime.getNano(),
startedAt.atOffset(ZoneId.systemDefault().getRules().getOffset(startedAt)),
indexSkippedCounter));
} else {
searchIndex =
searchIndex.setComment(
"Indexed %s features in %s.%s seconds, started at %s."
.formatted(
total,
processTime.getSeconds(),
processTime.getNano(),
startedAt.atOffset(ZoneId.systemDefault().getRules().getOffset(startedAt))));
}

return searchIndexRepository.save(
searchIndex.setLastIndexed(finishedAtOffset).setStatus(SearchIndex.Status.INDEXED));
searchIndex
.setLastIndexed(finishedAtOffset)
.setStatus(SearchIndex.Status.INDEXED)
.setSummary(
summary
.total(total)
.skippedCounter(indexSkippedCounter)
.duration(
BigDecimal.valueOf(processTime.getSeconds())
.add(BigDecimal.valueOf(processTime.getNano(), 9))
.doubleValue())
.errorMessage(null)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
alter table if exists search_index
drop column comment;
alter table if exists search_index
add column summary jsonb default null;
30 changes: 30 additions & 0 deletions src/main/resources/openapi/admin-schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,33 @@ components:
description: 'Priority of the task'
type: integer
nullable: true

SearchIndexSummary:
description: 'Summary of a search index run. This is created/updated when the index is finished.'
type: object
properties:
total:
description: 'Total number of features counted for indexing. When 0 or null, the index was cleared.'
type: integer
format: int32
nullable: true
skippedCounter:
description: 'Number of features skipped during indexing.'
type: integer
format: int32
nullable: true
startedAt:
description: 'Zoned date-time when the task started.'
type: string
format: date-time
nullable: true
example: '2024-12-13T11:30:40.863829185+01:00'
duration:
description: 'Time taken to index the source in seconds.'
type: number
format: double
nullable: true
errorMessage:
description: 'Error message if the task failed. Check the status field of the search index.'
type: string
nullable: true
14 changes: 8 additions & 6 deletions src/main/resources/openapi/viewer-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ components:
Layers:
description: 'An array of app layers.'
type: array
minLength: 0
minItems: 0
items:
$ref: './viewer-schemas.yaml#/components/schemas/AppLayer'

Expand Down Expand Up @@ -202,7 +202,7 @@ components:
components:
description: 'Configured components (controls) for the viewer'
type: array
minLength: 0
minItems: 0
items:
$ref: './viewer-schemas.yaml#/components/schemas/Component'
nullable: false
Expand Down Expand Up @@ -235,13 +235,13 @@ components:
features:
description: 'list of features. When the pagenumber*pagesize exceeds the number of features this list will be empty'
type: array
minLength: 0
minItems: 0
items:
$ref: './viewer-schemas.yaml#/components/schemas/Feature'
columnMetadata:
description: 'presentation metadata'
type: array
minLength: 0
minItems: 0
items:
$ref: './viewer-schemas.yaml#/components/schemas/ColumnMetadata'
template:
Expand All @@ -267,7 +267,7 @@ components:
values:
description: 'list of unique values'
type: array
minLength: 0
minItems: 0
uniqueItems: true
# any one type of string|number|boolean is allowed, but that generates unusable java code
# so allow any non-null value, we don't need to worry about mixed types as the data comes from a
Expand Down Expand Up @@ -300,7 +300,7 @@ components:
documents:
description: 'list of search documents. When the pagenumber*pagesize exceeds the number of documents this list will be empty'
type: array
minLength: 0
minItems: 0
items:
$ref: '#/components/schemas/SearchDocument'
example: { "total": 2,
Expand Down Expand Up @@ -1366,6 +1366,7 @@ paths:
/page:
summary: 'Use this endpoint to get the home page'
get:
operationId: 'getHomePage'
responses:
'200':
description: 'OK'
Expand All @@ -1389,6 +1390,7 @@ paths:
schema:
type: string
get:
operationId: 'getPage'
responses:
'200':
description: 'OK'
Expand Down
6 changes: 3 additions & 3 deletions src/main/resources/openapi/viewer-schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ components:
attributes:
description: 'feature attributes in key/value pairs'
type: object
minItems: 1
minProperties: 1
additionalProperties: true
example:
__fid: 1
Expand Down Expand Up @@ -439,13 +439,13 @@ components:
tiles:
description: list of tiles, tiles are used to link to applications or other pages
type: array
minLength: 0
minItems: 0
items:
$ref: '#/components/schemas/ViewerPageTile'
menu:
description: list of menu items for this page
type: array
minLength: 0
minItems: 0
items:
$ref: '#/components/schemas/ViewerMenuItem'

Expand Down

0 comments on commit 570fd4d

Please sign in to comment.