From cc8990eb367e1257947440a49ed670d3298ffaf3 Mon Sep 17 00:00:00 2001 From: SvitlanaKovalova1 Date: Tue, 7 Jan 2025 09:30:51 +0200 Subject: [PATCH] fix(call-number) fix issues after resolving merge conflict. --- .../folio/search/service/ResourceService.java | 1 - .../impl/CallNumberResourceExtractor.java | 123 +----------- .../impl/ClassificationResourceExtractor.java | 3 +- .../impl/ContributorResourceExtractor.java | 1 + .../impl/SubjectResourceExtractor.java | 1 + .../reindex/jdbc/CallNumberRepository.java | 179 +++++++++++++----- .../reindex/jdbc/ContributorRepository.java | 28 --- .../reindex/jdbc/SubjectRepository.java | 28 --- .../v4.1/create_call_number_tables.xml | 26 +++ .../search/controller/BrowseCallNumberIT.java | 4 +- .../integration/ReindexKafkaListenerIT.java | 8 +- .../InstanceChildrenResourceServiceTest.java | 4 + .../CallNumberResourceExtractorTest.java | 2 +- .../reindex/jdbc/CallNumberRepositoryIT.java | 8 +- 14 files changed, 184 insertions(+), 232 deletions(-) diff --git a/src/main/java/org/folio/search/service/ResourceService.java b/src/main/java/org/folio/search/service/ResourceService.java index cc1787e60..f76a543bf 100644 --- a/src/main/java/org/folio/search/service/ResourceService.java +++ b/src/main/java/org/folio/search/service/ResourceService.java @@ -103,7 +103,6 @@ public FolioIndexOperationResponse indexInstancesById(List resour private Map> processIndexInstanceEvents(List resourceEvents) { var indexEvents = extractEventsForDataMove(resourceEvents); - preProcessEvents(indexEvents); var fetchedInstances = Optional.ofNullable(consortiumTenantExecutor.execute( () -> resourceFetchService.fetchInstancesByIds(indexEvents))) .orElse(Collections.emptyList()).stream() diff --git a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/CallNumberResourceExtractor.java b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/CallNumberResourceExtractor.java index f1d722de1..c09f30ab1 100644 --- a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/CallNumberResourceExtractor.java +++ b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/CallNumberResourceExtractor.java @@ -1,34 +1,23 @@ package org.folio.search.service.converter.preprocessor.extractor.impl; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptySet; import static org.apache.commons.collections4.MapUtils.getMap; import static org.apache.commons.collections4.MapUtils.getString; -import static org.folio.search.utils.CollectionUtils.subtract; import static org.folio.search.utils.SearchConverterUtils.getNewAsMap; -import static org.folio.search.utils.SearchConverterUtils.getOldAsMap; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import lombok.extern.log4j.Log4j2; import org.folio.search.domain.dto.ResourceEvent; -import org.folio.search.domain.dto.ResourceEventType; import org.folio.search.domain.dto.TenantConfiguredFeature; import org.folio.search.model.entity.CallNumberEntity; import org.folio.search.model.entity.InstanceCallNumberEntity; -import org.folio.search.model.entity.InstanceCallNumberEntityAgg; -import org.folio.search.model.index.CallNumberResource; import org.folio.search.model.types.ResourceType; import org.folio.search.service.FeatureConfigService; -import org.folio.search.service.consortium.ConsortiumTenantProvider; import org.folio.search.service.converter.preprocessor.extractor.ChildResourceExtractor; import org.folio.search.service.reindex.jdbc.CallNumberRepository; -import org.folio.search.utils.CollectionUtils; import org.folio.search.utils.JsonConverter; import org.springframework.stereotype.Component; @@ -46,67 +35,15 @@ public class CallNumberResourceExtractor extends ChildResourceExtractor { public static final String ENUMERATION_FIELD = "enumeration"; public static final String COPY_NUMBER_FIELD = "copyNumber"; - private final CallNumberRepository repository; private final JsonConverter jsonConverter; private final FeatureConfigService featureConfigService; - private final ConsortiumTenantProvider tenantProvider; public CallNumberResourceExtractor(CallNumberRepository repository, JsonConverter jsonConverter, - FeatureConfigService featureConfigService, - ConsortiumTenantProvider tenantProvider) { + FeatureConfigService featureConfigService) { super(repository); - this.repository = repository; this.jsonConverter = jsonConverter; this.featureConfigService = featureConfigService; - this.tenantProvider = tenantProvider; - } - - @Override - public List prepareEvents(ResourceEvent resource) { - if (!featureConfigService.isEnabled(TenantConfiguredFeature.BROWSE_CALL_NUMBERS)) { - return Collections.emptyList(); - } - var oldCallNumbers = getCallNumberResources(getOldAsMap(resource)); - var newCallNumbers = getCallNumberResources(getNewAsMap(resource)); - - if (oldCallNumbers.equals(newCallNumbers)) { - return emptyList(); - } - - var tenant = resource.getTenant(); - var callNumbersForCreate = subtract(newCallNumbers, oldCallNumbers); - var callNumbersForDelete = subtract(oldCallNumbers, newCallNumbers); - - var idsForCreate = toIds(callNumbersForCreate); - var idsForDelete = toIds(callNumbersForDelete); - - List idsForFetch = new ArrayList<>(); - idsForFetch.addAll(idsForCreate); - idsForFetch.addAll(idsForDelete); - - var entityAggList = repository.fetchByIds(idsForFetch); - var list = getResourceEventsForDeletion(idsForDelete, entityAggList, tenant); - - var list1 = entityAggList.stream() - .map(entities -> toResourceEvent(entities, tenant)) - .toList(); - return CollectionUtils.mergeSafelyToList(list, list1); - } - - @Override - public List prepareEventsOnSharing(ResourceEvent resource) { - return emptyList(); - } - - @Override - public boolean hasChildResourceChanges(ResourceEvent resource) { - if (!featureConfigService.isEnabled(TenantConfiguredFeature.BROWSE_CALL_NUMBERS)) { - return false; - } - var oldCallNumber = toCallNumberEntity(getOldAsMap(resource)); - var newCallNumber = toCallNumberEntity(getNewAsMap(resource)); - return !oldCallNumber.equals(newCallNumber); } @Override @@ -132,6 +69,9 @@ protected List> constructRelations(boolean shared, ResourceE @Override protected Map constructEntity(Map entityProperties) { + if (entityProperties == null) { + return null; + } if (!featureConfigService.isEnabled(TenantConfiguredFeature.BROWSE_CALL_NUMBERS)) { return Collections.emptyMap(); } @@ -150,61 +90,6 @@ protected Set> getChildResources(Map event) return Set.of(event); } - private Set getCallNumberResources(Map event) { - return toCallNumberEntity(event) - .map(Set::of) - .orElse(emptySet()); - } - - private List toIds(Set subtract) { - return subtract.stream() - .map(CallNumberEntity::getId) - .collect(Collectors.toCollection(ArrayList::new)); - } - - private List getResourceEventsForDeletion(List idsForDelete, - List entityAggList, - String tenant) { - var notFoundEntitiesForDelete = new ArrayList<>(idsForDelete); - var iterator = notFoundEntitiesForDelete.iterator(); - while (iterator.hasNext()) { - var callNumber = iterator.next(); - for (var agg : entityAggList) { - if (agg.id().equals(callNumber)) { - iterator.remove(); - } - } - } - - return notFoundEntitiesForDelete.stream() - .map(callNumberId -> toResourceDeleteEvent(callNumberId, tenant)) - .toList(); - } - - private ResourceEvent toResourceDeleteEvent(String id, String tenant) { - return new ResourceEvent() - .id(id) - .tenant(tenant) - .resourceName(ResourceType.INSTANCE_CALL_NUMBER.getName()) - .type(ResourceEventType.DELETE); - } - - private ResourceEvent toResourceEvent(InstanceCallNumberEntityAgg source, String tenant) { - var id = source.id(); - var resource = new CallNumberResource(id, source.fullCallNumber(), source.callNumber(), - source.callNumberPrefix(), source.callNumberSuffix(), source.callNumberTypeId(), source.volume(), - source.enumeration(), source.chronology(), source.copyNumber(), source.instances()); - for (var instance : source.instances()) { - instance.setShared(tenantProvider.isCentralTenant(instance.getTenantId())); - } - return new ResourceEvent() - .id(id) - .tenant(tenant) - .resourceName(ResourceType.INSTANCE_CALL_NUMBER.getName()) - .type(ResourceEventType.UPDATE) - ._new(jsonConverter.convertToMap(resource)); - } - private Optional toCallNumberEntity(Map entityProperties) { var callNumberComponents = getCallNumberComponents(entityProperties); var callNumber = getString(callNumberComponents, CALL_NUMBER_FIELD); diff --git a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ClassificationResourceExtractor.java b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ClassificationResourceExtractor.java index e25b0c9ef..c4cdcb02e 100644 --- a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ClassificationResourceExtractor.java +++ b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ClassificationResourceExtractor.java @@ -27,7 +27,8 @@ public class ClassificationResourceExtractor extends ChildResourceExtractor { private final FeatureConfigService featureConfigService; - public ClassificationResourceExtractor(ClassificationRepository repository, FeatureConfigService featureConfigService) { + public ClassificationResourceExtractor(ClassificationRepository repository, + FeatureConfigService featureConfigService) { super(repository); this.featureConfigService = featureConfigService; } diff --git a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ContributorResourceExtractor.java b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ContributorResourceExtractor.java index a8f96e772..35bd072b9 100644 --- a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ContributorResourceExtractor.java +++ b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/ContributorResourceExtractor.java @@ -12,6 +12,7 @@ import java.util.Objects; import lombok.extern.log4j.Log4j2; import org.folio.search.domain.dto.ResourceEvent; +import org.folio.search.model.types.ResourceType; import org.folio.search.service.converter.preprocessor.extractor.ChildResourceExtractor; import org.folio.search.service.reindex.jdbc.ContributorRepository; import org.folio.search.utils.ShaUtils; diff --git a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/SubjectResourceExtractor.java b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/SubjectResourceExtractor.java index e912c3f16..94ea0ca82 100644 --- a/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/SubjectResourceExtractor.java +++ b/src/main/java/org/folio/search/service/converter/preprocessor/extractor/impl/SubjectResourceExtractor.java @@ -14,6 +14,7 @@ import java.util.Objects; import lombok.extern.log4j.Log4j2; import org.folio.search.domain.dto.ResourceEvent; +import org.folio.search.model.types.ResourceType; import org.folio.search.service.converter.preprocessor.extractor.ChildResourceExtractor; import org.folio.search.service.reindex.jdbc.SubjectRepository; import org.folio.search.utils.ShaUtils; diff --git a/src/main/java/org/folio/search/service/reindex/jdbc/CallNumberRepository.java b/src/main/java/org/folio/search/service/reindex/jdbc/CallNumberRepository.java index 45ccaebf3..afc2ac5d9 100644 --- a/src/main/java/org/folio/search/service/reindex/jdbc/CallNumberRepository.java +++ b/src/main/java/org/folio/search/service/reindex/jdbc/CallNumberRepository.java @@ -1,25 +1,26 @@ package org.folio.search.service.reindex.jdbc; import static org.apache.commons.collections4.MapUtils.getString; +import static org.folio.search.service.converter.preprocessor.extractor.impl.CallNumberResourceExtractor.CHRONOLOGY_FIELD; +import static org.folio.search.service.converter.preprocessor.extractor.impl.CallNumberResourceExtractor.ENUMERATION_FIELD; +import static org.folio.search.service.converter.preprocessor.extractor.impl.CallNumberResourceExtractor.VOLUME_FIELD; import static org.folio.search.service.reindex.ReindexConstants.CALL_NUMBER_TABLE; import static org.folio.search.service.reindex.ReindexConstants.INSTANCE_CALL_NUMBER_TABLE; -import static org.folio.search.utils.CallNumberUtils.calculateFullCallNumber; import static org.folio.search.utils.JdbcUtils.getFullTableName; -import static org.folio.search.utils.JdbcUtils.getParamPlaceholder; import static org.folio.search.utils.JdbcUtils.getParamPlaceholderForUuid; +import static org.folio.search.utils.SearchUtils.SUB_RESOURCE_INSTANCES_FIELD; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Collections; +import java.sql.Timestamp; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import lombok.extern.log4j.Log4j2; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; import org.folio.search.configuration.properties.ReindexConfigurationProperties; import org.folio.search.model.entity.ChildResourceEntityBatch; -import org.folio.search.model.entity.InstanceCallNumberEntityAgg; import org.folio.search.model.types.ReindexEntityType; import org.folio.search.utils.JdbcUtils; import org.folio.search.utils.JsonConverter; @@ -55,9 +56,81 @@ public class CallNumberRepository extends UploadRangeRepository implements Insta """; private static final String DELETE_QUERY = """ - DELETE - FROM %s - WHERE instance_id IN (%s); + WITH deleted_ids as ( + DELETE + FROM %1$s.instance_call_number + WHERE instance_id IN (%2$s) + RETURNING call_number_id + ) + UPDATE %1$s.call_number + SET last_updated_date = CURRENT_TIMESTAMP + WHERE id IN (SELECT * FROM deleted_ids); + """; + + private static final String SELECT_BY_UPDATED_QUERY = """ + WITH cte AS ( + SELECT + id, + call_number, + call_number_prefix, + call_number_suffix, + call_number_type_id, + volume, + enumeration, + chronology, + copy_number, + last_updated_date + FROM %1$s.call_number + WHERE last_updated_date > ? + ORDER BY last_updated_date + ) + SELECT + c.id, + c.call_number, + c.call_number_prefix, + c.call_number_suffix, + c.call_number_type_id, + c.volume, + c.enumeration, + c.chronology, + c.copy_number, + c.last_updated_date, + json_agg( + CASE + WHEN sub.instance_count IS NULL THEN NULL + ELSE json_build_object( + 'count', sub.instance_count, + 'tenantId', sub.tenant_id, + 'locationId', sub.location_ids + ) + END + ) AS instances + FROM cte c + LEFT JOIN ( + SELECT + cte.id, + ins.tenant_id, + array_agg(DISTINCT ins.location_id) FILTER (WHERE ins.location_id IS NOT NULL) AS location_ids, + count(DISTINCT ins.instance_id) AS instance_count + FROM %1$s.instance_call_number ins + INNER JOIN cte ON ins.call_number_id = cte.id + GROUP BY + cte.id, + ins.tenant_id + ) sub ON c.id = sub.id + GROUP BY + c.id, + c.call_number, + c.call_number_prefix, + c.call_number_suffix, + c.call_number_type_id, + c.volume, + c.enumeration, + c.chronology, + c.copy_number, + c.last_updated_date + ORDER BY + last_updated_date ASC; """; private static final String INSERT_ENTITIES_SQL = """ @@ -72,7 +145,7 @@ public class CallNumberRepository extends UploadRangeRepository implements Insta chronology, copy_number ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) - ON CONFLICT DO NOTHING; + ON CONFLICT (id) DO UPDATE SET last_updated_date = CURRENT_TIMESTAMP; """; private static final String INSERT_RELATIONS_SQL = """ @@ -88,8 +161,6 @@ public class CallNumberRepository extends UploadRangeRepository implements Insta private static final String ID_RANGE_INS_WHERE_CLAUSE = "ins.call_number_id >= ? AND ins.call_number_id <= ?"; private static final String ID_RANGE_CLAS_WHERE_CLAUSE = "c.id >= ? AND c.id <= ?"; - private static final String IDS_INS_WHERE_CLAUSE = "ins.call_number_id IN (%1$s)"; - private static final String IDS_CLAS_WHERE_CLAUSE = "c.id IN (%1$s)"; protected CallNumberRepository(JdbcTemplate jdbcTemplate, JsonConverter jsonConverter, FolioExecutionContext context, ReindexConfigurationProperties reindexConfig) { @@ -98,8 +169,7 @@ protected CallNumberRepository(JdbcTemplate jdbcTemplate, JsonConverter jsonConv @Override public void deleteByInstanceIds(List instanceIds) { - var sql = DELETE_QUERY.formatted(getFullTableName(context, INSTANCE_CALL_NUMBER_TABLE), - getParamPlaceholderForUuid(instanceIds.size())); + var sql = DELETE_QUERY.formatted(JdbcUtils.getSchemaName(context), getParamPlaceholderForUuid(instanceIds.size())); jdbcTemplate.update(sql, instanceIds.toArray()); } @@ -124,23 +194,18 @@ protected Optional subEntityTable() { return Optional.of(INSTANCE_CALL_NUMBER_TABLE); } - public List fetchByIds(List ids) { - if (CollectionUtils.isEmpty(ids)) { - return Collections.emptyList(); - } - var sql = SELECT_QUERY.formatted(JdbcUtils.getSchemaName(context), - IDS_INS_WHERE_CLAUSE.formatted(getParamPlaceholder(ids.size())), - IDS_CLAS_WHERE_CLAUSE.formatted(getParamPlaceholder(ids.size()))); - return jdbcTemplate.query(sql, instanceCallNumberAggRowMapper(), ListUtils.union(ids, ids).toArray()); - } - @Override public List> fetchByIdRange(String lower, String upper) { var sql = getFetchBySql(); - return jdbcTemplate.query(sql, instanceCallNumberAggRowMapper(), lower, upper, lower, upper) - .stream() - .map(jsonConverter::convertToMap) - .toList(); + return jdbcTemplate.query(sql, rowToMapMapper(), lower, upper, lower, upper); + } + + @Override + public SubResourceResult fetchByTimestamp(String tenant, Timestamp timestamp) { + var sql = SELECT_BY_UPDATED_QUERY.formatted(JdbcUtils.getSchemaName(tenant, context.getFolioModuleMetadata())); + var records = jdbcTemplate.query(sql, rowToMapMapper2(), timestamp); + var lastUpdateDate = records.isEmpty() ? null : records.get(records.size() - 1).get(LAST_UPDATED_DATE_FIELD); + return new SubResourceResult(records, (Timestamp) lastUpdateDate); } @Override @@ -151,7 +216,48 @@ protected String getFetchBySql() { @Override protected RowMapper> rowToMapMapper() { - return null; + return (rs, rowNum) -> { + Map callNumber = new HashMap<>(); + callNumber.put("id", getId(rs)); + callNumber.put("callNumber", getCallNumber(rs)); + callNumber.put("callNumberPrefix", getCallNumberPrefix(rs)); + callNumber.put("callNumberSuffix", getCallNumberSuffix(rs)); + callNumber.put("callNumberTypeId", getCallNumberTypeId(rs)); + callNumber.put(VOLUME_FIELD, getVolume(rs)); + callNumber.put(ENUMERATION_FIELD, getEnumeration(rs)); + callNumber.put(CHRONOLOGY_FIELD, getChronology(rs)); + callNumber.put("copyNumber", getCopyNumber(rs)); + + var maps = jsonConverter.fromJsonToListOfMaps(getInstances(rs)).stream().filter(Objects::nonNull).toList(); + if (!maps.isEmpty()) { + callNumber.put(SUB_RESOURCE_INSTANCES_FIELD, maps); + } + + return callNumber; + }; + } + + protected RowMapper> rowToMapMapper2() { + return (rs, rowNum) -> { + Map callNumber = new HashMap<>(); + callNumber.put("id", getId(rs)); + callNumber.put("callNumber", getCallNumber(rs)); + callNumber.put("callNumberPrefix", getCallNumberPrefix(rs)); + callNumber.put("callNumberSuffix", getCallNumberSuffix(rs)); + callNumber.put("callNumberTypeId", getCallNumberTypeId(rs)); + callNumber.put(VOLUME_FIELD, getVolume(rs)); + callNumber.put(ENUMERATION_FIELD, getEnumeration(rs)); + callNumber.put(CHRONOLOGY_FIELD, getChronology(rs)); + callNumber.put("copyNumber", getCopyNumber(rs)); + callNumber.put(LAST_UPDATED_DATE_FIELD, rs.getTimestamp("last_updated_date")); + + var maps = jsonConverter.fromJsonToListOfMaps(getInstances(rs)).stream().filter(Objects::nonNull).toList(); + if (!maps.isEmpty()) { + callNumber.put(SUB_RESOURCE_INSTANCES_FIELD, maps); + } + + return callNumber; + }; } private void saveResourceEntities(ChildResourceEntityBatch entityBatch) { @@ -202,21 +308,6 @@ private void saveRelationshipEntities(ChildResourceEntityBatch entityBatch) { } } - private RowMapper instanceCallNumberAggRowMapper() { - return (rs, rowNum) -> { - var callNumber = getCallNumber(rs); - var callNumberSuffix = getCallNumberSuffix(rs); - var volume = getVolume(rs); - var enumeration = getEnumeration(rs); - var chronology = getChronology(rs); - var copyNumber = getCopyNumber(rs); - return new InstanceCallNumberEntityAgg(getId(rs), - calculateFullCallNumber(callNumber, volume, enumeration, chronology, copyNumber, callNumberSuffix), - callNumber, getCallNumberPrefix(rs), callNumberSuffix, getCallNumberTypeId(rs), volume, enumeration, chronology, - copyNumber, parseInstanceSubResources(getInstances(rs))); - }; - } - private String getCallNumberSuffix(ResultSet rs) throws SQLException { return rs.getString("call_number_suffix"); } diff --git a/src/main/java/org/folio/search/service/reindex/jdbc/ContributorRepository.java b/src/main/java/org/folio/search/service/reindex/jdbc/ContributorRepository.java index e82b50b98..5468a550b 100644 --- a/src/main/java/org/folio/search/service/reindex/jdbc/ContributorRepository.java +++ b/src/main/java/org/folio/search/service/reindex/jdbc/ContributorRepository.java @@ -1,6 +1,5 @@ package org.folio.search.service.reindex.jdbc; -import static org.folio.search.utils.JdbcUtils.getParamPlaceholder; import static org.folio.search.utils.JdbcUtils.getParamPlaceholderForUuid; import static org.folio.search.utils.SearchUtils.AUTHORITY_ID_FIELD; import static org.folio.search.utils.SearchUtils.CONTRIBUTOR_TYPE_FIELD; @@ -9,18 +8,14 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import lombok.extern.log4j.Log4j2; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; import org.folio.search.configuration.properties.ReindexConfigurationProperties; import org.folio.search.model.entity.ChildResourceEntityBatch; -import org.folio.search.model.entity.InstanceContributorEntityAgg; import org.folio.search.model.types.ReindexEntityType; import org.folio.search.service.reindex.ReindexConstants; import org.folio.search.utils.JdbcUtils; @@ -147,8 +142,6 @@ WHERE instance_id IN (%2$s) private static final String ID_RANGE_INS_WHERE_CLAUSE = "ins.contributor_id >= ? AND ins.contributor_id <= ?"; private static final String ID_RANGE_CONTR_WHERE_CLAUSE = "c.id >= ? AND c.id <= ?"; - private static final String IDS_INS_WHERE_CLAUSE = "ins.contributor_id IN (%1$s)"; - private static final String IDS_CONTR_WHERE_CLAUSE = "c.id IN (%1$s)"; protected ContributorRepository(JdbcTemplate jdbcTemplate, JsonConverter jsonConverter, FolioExecutionContext context, @@ -171,17 +164,6 @@ protected Optional subEntityTable() { return Optional.of(ReindexConstants.INSTANCE_CONTRIBUTOR_TABLE); } - public List fetchByIds(List ids) { - if (CollectionUtils.isEmpty(ids)) { - return Collections.emptyList(); - } - var sql = SELECT_QUERY.formatted(JdbcUtils.getSchemaName(context), - IDS_INS_WHERE_CLAUSE.formatted(getParamPlaceholder(ids.size())), - IDS_CONTR_WHERE_CLAUSE.formatted(getParamPlaceholder(ids.size())) - ); - return jdbcTemplate.query(sql, instanceAggRowMapper(), ListUtils.union(ids, ids).toArray()); - } - @Override public List> fetchByIdRange(String lower, String upper) { var sql = getFetchBySql(); @@ -282,16 +264,6 @@ public void saveAll(ChildResourceEntityBatch entityBatch) { } } - private RowMapper instanceAggRowMapper() { - return (rs, rowNum) -> new InstanceContributorEntityAgg( - getId(rs), - getName(rs), - getNameTypeId(rs), - getAuthorityId(rs), - parseInstanceSubResources(getInstances(rs)) - ); - } - private String getId(ResultSet rs) throws SQLException { return rs.getString("id"); } diff --git a/src/main/java/org/folio/search/service/reindex/jdbc/SubjectRepository.java b/src/main/java/org/folio/search/service/reindex/jdbc/SubjectRepository.java index ed36187d5..64559d79c 100644 --- a/src/main/java/org/folio/search/service/reindex/jdbc/SubjectRepository.java +++ b/src/main/java/org/folio/search/service/reindex/jdbc/SubjectRepository.java @@ -1,6 +1,5 @@ package org.folio.search.service.reindex.jdbc; -import static org.folio.search.utils.JdbcUtils.getParamPlaceholder; import static org.folio.search.utils.JdbcUtils.getParamPlaceholderForUuid; import static org.folio.search.utils.SearchUtils.AUTHORITY_ID_FIELD; import static org.folio.search.utils.SearchUtils.SUBJECT_SOURCE_ID_FIELD; @@ -11,18 +10,14 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import lombok.extern.log4j.Log4j2; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; import org.folio.search.configuration.properties.ReindexConfigurationProperties; import org.folio.search.model.entity.ChildResourceEntityBatch; -import org.folio.search.model.entity.InstanceSubjectEntityAgg; import org.folio.search.model.types.ReindexEntityType; import org.folio.search.service.reindex.ReindexConstants; import org.folio.search.utils.JdbcUtils; @@ -147,8 +142,6 @@ WHERE instance_id IN (%2$s) private static final String ID_RANGE_INS_WHERE_CLAUSE = "ins.subject_id >= ? AND ins.subject_id <= ?"; private static final String ID_RANGE_SUBJ_WHERE_CLAUSE = "s.id >= ? AND s.id <= ?"; - private static final String IDS_INS_WHERE_CLAUSE = "ins.subject_id IN (%1$s)"; - private static final String IDS_SUB_WHERE_CLAUSE = "s.id IN (%1$s)"; protected SubjectRepository(JdbcTemplate jdbcTemplate, JsonConverter jsonConverter, @@ -172,16 +165,6 @@ protected Optional subEntityTable() { return Optional.of(ReindexConstants.INSTANCE_SUBJECT_TABLE); } - public List fetchByIds(List ids) { - if (CollectionUtils.isEmpty(ids)) { - return Collections.emptyList(); - } - var sql = SELECT_QUERY.formatted(JdbcUtils.getSchemaName(context), - IDS_INS_WHERE_CLAUSE.formatted(getParamPlaceholder(ids.size())), - IDS_SUB_WHERE_CLAUSE.formatted(getParamPlaceholder(ids.size()))); - return jdbcTemplate.query(sql, instanceAggRowMapper(), ListUtils.union(ids, ids).toArray()); - } - @Override public List> fetchByIdRange(String lower, String upper) { var sql = getFetchBySql(); @@ -285,17 +268,6 @@ public void saveAll(ChildResourceEntityBatch entityBatch) { } } - private RowMapper instanceAggRowMapper() { - return (rs, rowNum) -> new InstanceSubjectEntityAgg( - getId(rs), - getValue(rs), - getAuthorityId(rs), - getSourceId(rs), - getTypeId(rs), - parseInstanceSubResources(getInstances(rs)) - ); - } - private String getId(ResultSet rs) throws SQLException { return rs.getString("id"); } diff --git a/src/main/resources/changelog/changes/v4.1/create_call_number_tables.xml b/src/main/resources/changelog/changes/v4.1/create_call_number_tables.xml index 6b72359f4..6e6d1e51b 100644 --- a/src/main/resources/changelog/changes/v4.1/create_call_number_tables.xml +++ b/src/main/resources/changelog/changes/v4.1/create_call_number_tables.xml @@ -60,4 +60,30 @@ + + + + + + + + + + + + + + + + + + Fill sub_resources_lock table with initial records + + + + + + + + diff --git a/src/test/java/org/folio/search/controller/BrowseCallNumberIT.java b/src/test/java/org/folio/search/controller/BrowseCallNumberIT.java index 3a07eb4f8..38e578963 100644 --- a/src/test/java/org/folio/search/controller/BrowseCallNumberIT.java +++ b/src/test/java/org/folio/search/controller/BrowseCallNumberIT.java @@ -4,8 +4,8 @@ import static java.util.function.Function.identity; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.awaitility.Durations.ONE_MINUTE; import static org.awaitility.Durations.ONE_SECOND; +import static org.awaitility.Durations.TWO_MINUTES; import static org.folio.search.support.base.ApiEndpoints.browseConfigPath; import static org.folio.search.support.base.ApiEndpoints.instanceCallNumberBrowsePath; import static org.folio.search.support.base.ApiEndpoints.recordFacetsPath; @@ -56,7 +56,7 @@ class BrowseCallNumberIT extends BaseIntegrationTest { @BeforeAll static void prepare() { setUpTenant(CallNumberTestData.instances().toArray(Instance[]::new)); - await().atMost(ONE_MINUTE).pollInterval(ONE_SECOND).untilAsserted(() -> { + await().atMost(TWO_MINUTES).pollInterval(ONE_SECOND).untilAsserted(() -> { var counted = countIndexDocument(ResourceType.INSTANCE_CALL_NUMBER, TENANT_ID); assertThat(counted).isEqualTo(100); }); diff --git a/src/test/java/org/folio/search/integration/ReindexKafkaListenerIT.java b/src/test/java/org/folio/search/integration/ReindexKafkaListenerIT.java index 17b2ecd29..591402216 100644 --- a/src/test/java/org/folio/search/integration/ReindexKafkaListenerIT.java +++ b/src/test/java/org/folio/search/integration/ReindexKafkaListenerIT.java @@ -49,13 +49,13 @@ import org.springframework.boot.autoconfigure.kafka.KafkaProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.kafka.core.DefaultKafkaProducerFactory; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.kafka.support.serializer.JsonSerializer; import org.springframework.retry.annotation.EnableRetry; +import org.springframework.test.context.bean.override.mockito.MockitoBean; @EnableKafka @IntegrationTest @@ -68,11 +68,11 @@ class ReindexKafkaListenerIT { static final String FOLIO_ENV_VAL = "reindex-listener-it"; static final String FOLIO_ENV = "folio.environment=" + FOLIO_ENV_VAL; - @MockBean + @MockitoBean private ConsortiumTenantExecutor executionService; - @MockBean + @MockitoBean private SystemUserScopedExecutionService systemUserScopedExecutionService; - @MockBean + @MockitoBean private ReindexOrchestrationService reindexService; @Autowired private KafkaTemplate rangeKafkaTemplate; diff --git a/src/test/java/org/folio/search/service/InstanceChildrenResourceServiceTest.java b/src/test/java/org/folio/search/service/InstanceChildrenResourceServiceTest.java index bb4f06006..d7c471833 100644 --- a/src/test/java/org/folio/search/service/InstanceChildrenResourceServiceTest.java +++ b/src/test/java/org/folio/search/service/InstanceChildrenResourceServiceTest.java @@ -1,6 +1,7 @@ package org.folio.search.service; import static org.folio.search.utils.TestConstants.TENANT_ID; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -43,6 +44,9 @@ class InstanceChildrenResourceServiceTest { void setUp() { this.resourceExtractors = List.of(classificationResourceExtractor, contributorResourceExtractor, subjectResourceExtractor); + for (var resourceExtractor : resourceExtractors) { + lenient().when(resourceExtractor.resourceType()).thenReturn(ResourceType.INSTANCE); + } service = new InstanceChildrenResourceService(resourceExtractors, consortiumTenantProvider); } diff --git a/src/test/java/org/folio/search/service/converter/preprocessor/extractor/CallNumberResourceExtractorTest.java b/src/test/java/org/folio/search/service/converter/preprocessor/extractor/CallNumberResourceExtractorTest.java index d0f4af0d7..b2a037cff 100644 --- a/src/test/java/org/folio/search/service/converter/preprocessor/extractor/CallNumberResourceExtractorTest.java +++ b/src/test/java/org/folio/search/service/converter/preprocessor/extractor/CallNumberResourceExtractorTest.java @@ -50,7 +50,7 @@ protected int getExpectedEntitiesSize() { void setUp() { extractor = new CallNumberResourceExtractor(repository, new JsonConverter(new ObjectMapper()), - featureConfigService, tenantProvider); + featureConfigService); } @Test diff --git a/src/test/java/org/folio/search/service/reindex/jdbc/CallNumberRepositoryIT.java b/src/test/java/org/folio/search/service/reindex/jdbc/CallNumberRepositoryIT.java index 2006e1cf9..75d83a9e3 100644 --- a/src/test/java/org/folio/search/service/reindex/jdbc/CallNumberRepositoryIT.java +++ b/src/test/java/org/folio/search/service/reindex/jdbc/CallNumberRepositoryIT.java @@ -25,9 +25,9 @@ import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.boot.test.autoconfigure.json.AutoConfigureJson; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.jdbc.Sql; @IntegrationTest @@ -38,8 +38,8 @@ @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class CallNumberRepositoryIT { - private @SpyBean JdbcTemplate jdbcTemplate; - private @MockBean FolioExecutionContext context; + private @MockitoSpyBean JdbcTemplate jdbcTemplate; + private @MockitoBean FolioExecutionContext context; private CallNumberRepository repository; private ReindexConfigurationProperties properties;