Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIRC-2223 Release 24.3.10 #1541

Merged
merged 4 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 24.3.10 2025-01-18
* Address search slips high memory consumption (CIRC-2167)

## 24.3.9 2025-01-17
* Support DCB re-request (CIRC-2198)

Expand Down
5 changes: 4 additions & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@
],
"pathPattern": "/circulation/search-slips/{servicePointId}",
"permissionsRequired": [
"circulation.search-slips.get"
"circulation.search-slips.get",
"mod-settings.entries.item.get",
"mod-settings.entries.collection.get",
"mod-settings.global.read.circulation"
],
"modulePermissions": [
"modperms.circulation.search-slips.get"
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>mod-circulation</artifactId>
<groupId>org.folio</groupId>
<version>24.3.10-SNAPSHOT</version>
<version>24.3.11-SNAPSHOT</version>
<licenses>
<license>
<name>Apache License 2.0</name>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.folio.circulation.domain.configuration;

import io.vertx.core.json.JsonObject;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import static org.folio.circulation.support.json.JsonPropertyFetcher.getBooleanProperty;

@AllArgsConstructor
@Getter
@ToString(onlyExplicitlyIncluded = true)
public class PrintHoldRequestsConfiguration {

@ToString.Include
private final boolean printHoldRequestsEnabled;

public static PrintHoldRequestsConfiguration from(JsonObject jsonObject) {
return new PrintHoldRequestsConfiguration(getBooleanProperty(jsonObject,
"printHoldRequestsEnabled"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.folio.circulation.domain.ConfigurationService;
import org.folio.circulation.domain.MultipleRecords;
import org.folio.circulation.domain.anonymization.config.LoanAnonymizationConfiguration;
import org.folio.circulation.domain.configuration.PrintHoldRequestsConfiguration;
import org.folio.circulation.domain.configuration.TlrSettingsConfiguration;
import org.folio.circulation.support.Clients;
import org.folio.circulation.support.GetManyRecordsClient;
Expand Down Expand Up @@ -59,6 +60,13 @@ public CompletableFuture<Result<TlrSettingsConfiguration>> lookupTlrSettings() {
return findAndMapFirstConfiguration(queryResult, TlrSettingsConfiguration::from);
}

public CompletableFuture<Result<PrintHoldRequestsConfiguration>> lookupPrintHoldRequestsEnabled() {
log.info("lookupPrintHoldRequestsEnabled:: fetching PrintHoldRequest configuration");

return findAndMapFirstConfiguration(defineModuleNameAndConfigNameFilter(
"SETTINGS", "PRINT_HOLD_REQUESTS"), PrintHoldRequestsConfiguration::from);
}

/**
* Gets loan history tenant configuration - settings for loan anonymization
*
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/org/folio/circulation/resources/SlipsResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
import org.folio.circulation.domain.RequestStatus;
import org.folio.circulation.domain.RequestType;
import org.folio.circulation.domain.ServicePoint;
import org.folio.circulation.domain.configuration.PrintHoldRequestsConfiguration;
import org.folio.circulation.domain.notice.TemplateContextUtil;
import org.folio.circulation.infrastructure.storage.ConfigurationRepository;
import org.folio.circulation.infrastructure.storage.ServicePointRepository;
import org.folio.circulation.infrastructure.storage.inventory.HoldingsRepository;
import org.folio.circulation.infrastructure.storage.inventory.InstanceRepository;
Expand All @@ -63,6 +65,7 @@

import io.vertx.core.http.HttpClient;
import io.vertx.core.json.JsonObject;
import io.vertx.core.json.JsonArray;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;

Expand All @@ -77,6 +80,7 @@ public abstract class SlipsResource extends Resource {
private static final String REQUEST_TYPE_KEY = "requestType";
private static final String REQUEST_LEVEL_KEY = "requestLevel";
private static final String TOTAL_RECORDS_KEY = "totalRecords";
private static final String SEARCH_SLIPS_KEY = "searchSlips";
private static final String SERVICE_POINT_ID_PARAM = "servicePointId";
private static final String EFFECTIVE_LOCATION_ID_KEY = "effectiveLocationId";
private static final String PRIMARY_SERVICE_POINT_KEY = "primaryServicePoint";
Expand Down Expand Up @@ -118,9 +122,15 @@ private void getMany(RoutingContext routingContext) {
final var servicePointRepository = new ServicePointRepository(clients);
final var patronGroupRepository = new PatronGroupRepository(clients);
final var departmentRepository = new DepartmentRepository(clients);
final var configurationRepository = new ConfigurationRepository(clients);
final UUID servicePointId = UUID.fromString(
routingContext.request().getParam(SERVICE_POINT_ID_PARAM));

if (SEARCH_SLIPS_KEY.equals(collectionName) && requestType == RequestType.HOLD) {
configurationRepository.lookupPrintHoldRequestsEnabled()
.thenAccept(r -> r.next(config -> returnNoRecordsIfSearchSlipsDisabled(config, context)));
}

fetchLocationsForServicePoint(servicePointId, clients)
.thenComposeAsync(r -> r.after(ctx -> fetchItemsForLocations(ctx,
itemRepository, LocationRepository.using(clients, servicePointRepository))))
Expand All @@ -138,6 +148,20 @@ private void getMany(RoutingContext routingContext) {
.thenAccept(context::writeResultToHttpResponse);
}

private Result<Object> returnNoRecordsIfSearchSlipsDisabled(PrintHoldRequestsConfiguration config,
WebContext context) {

if (config == null || !config.isPrintHoldRequestsEnabled()) {
log.info("returnNoRecordsIfSearchSlipsDisabled:: Print hold requests configuration is disabled");
context.writeResultToHttpResponse(succeeded(JsonHttpResponse.ok(
new io.vertx.core.json.JsonObject()
.put(SEARCH_SLIPS_KEY, new JsonArray())
.put(TOTAL_RECORDS_KEY, 0)
)));
}
return succeeded(null);
}

private CompletableFuture<Result<StaffSlipsContext>> fetchTitleLevelRequests(
StaffSlipsContext staffSlipsContext, Clients clients) {

Expand Down
9 changes: 9 additions & 0 deletions src/test/java/api/requests/SearchSlipsTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ class SearchSlipsTests extends APITests {

@Test
void responseShouldHaveEmptyListOfSearchSlipsRecords() {
configurationsFixture.configurePrintHoldRequests(true);
Response response = ResourceClient.forSearchSlips().getById(UUID.randomUUID());
assertThat(response.getStatusCode(), is(HTTP_OK));
assertResponseHasItems(response, 0);
}

@Test
void responseShouldHaveNoSearchSlipsRecords() {
configurationsFixture.configurePrintHoldRequests(false);
Response response = ResourceClient.forSearchSlips().getById(UUID.randomUUID());
assertThat(response.getStatusCode(), is(HTTP_OK));
assertResponseHasItems(response, 0);
Expand Down
13 changes: 13 additions & 0 deletions src/test/java/api/requests/StaffSlipsTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class StaffSlipsTests extends APITests {
@ParameterizedTest
@EnumSource(value = SlipsType.class)
void responseContainsNoSlipsForNonExistentServicePointId(SlipsType slipsType) {
configurationsFixture.configurePrintHoldRequests(true);
UUID servicePointId = servicePointsFixture.cd1().getId();
ItemResource item = itemsFixture.basedUponSmallAngryPlanet();

Expand All @@ -89,6 +90,7 @@ void responseContainsNoSlipsForNonExistentServicePointId(SlipsType slipsType) {
@ParameterizedTest
@EnumSource(value = SlipsType.class)
void responseContainsNoSlipsForWrongServicePointId(SlipsType slipsType) {
configurationsFixture.configurePrintHoldRequests(true);
UUID servicePointId = servicePointsFixture.cd1().getId();
ItemResource item = itemsFixture.basedUponSmallAngryPlanet();

Expand All @@ -109,6 +111,7 @@ void responseContainsNoSlipsForWrongServicePointId(SlipsType slipsType) {
@ParameterizedTest
@EnumSource(value = SlipsType.class)
void responseContainsNoSlipsWhenThereAreNoItems(SlipsType slipsType) {
configurationsFixture.configurePrintHoldRequests(true);
UUID servicePointId = servicePointsFixture.cd1().getId();
Response response = slipsType.get(servicePointId);

Expand All @@ -119,6 +122,7 @@ void responseContainsNoSlipsWhenThereAreNoItems(SlipsType slipsType) {
@ParameterizedTest
@EnumSource(value = SlipsType.class)
void responseContainsNoPickSlipsWhenItemHasOpenRequestWithWrongStatus(SlipsType slipsType) {
configurationsFixture.configurePrintHoldRequests(true);
UUID servicePointId = servicePointsFixture.cd1().getId();
ItemResource item = itemsFixture.basedUponSmallAngryPlanet();

Expand All @@ -142,6 +146,7 @@ void responseContainsNoPickSlipsWhenItemHasOpenRequestWithWrongStatus(SlipsType
@ParameterizedTest
@MethodSource(value = "getAllowedStatusesForHoldRequest")
void responseContainsSearchSlipsForItemWithAllowedStatus(ItemStatus itemStatus) {
configurationsFixture.configurePrintHoldRequests(true);
UUID servicePointId = servicePointsFixture.cd1().getId();
ItemResource item = itemsFixture.basedUponNod(b -> b.withStatus(itemStatus.getValue()));

Expand Down Expand Up @@ -182,6 +187,7 @@ private static Collection<ItemStatus> getAllowedStatusesForHoldRequest() {
})
void responseContainsSlipWithAllAvailableTokens(String countryCode, String primaryAddress,
String slipsTypeName) {
configurationsFixture.configurePrintHoldRequests(true);
SlipsType slipsType = SlipsType.valueOf(slipsTypeName);
IndividualResource servicePoint = servicePointsFixture.cd1();
UUID servicePointId = servicePoint.getId();
Expand Down Expand Up @@ -324,6 +330,7 @@ void responseContainsSlipWithAllAvailableTokens(String countryCode, String prima

@Test
void responseContainsPickSlipsForRequestsOfTypePageOnly() {
configurationsFixture.configurePrintHoldRequests(true);
UUID servicePointId = servicePointsFixture.cd1().getId();
val item = itemsFixture.basedUponSmallAngryPlanet();
val james = usersFixture.james();
Expand Down Expand Up @@ -354,6 +361,7 @@ void responseContainsPickSlipsForRequestsOfTypePageOnly() {

@Test
void responseContainsSearchSlipsForRequestsOfTypeHoldOnly() {
configurationsFixture.configurePrintHoldRequests(true);
UUID servicePointId = servicePointsFixture.cd1().getId();
val item = itemsFixture.basedUponSmallAngryPlanet();
UserResource steve = usersFixture.steve();
Expand Down Expand Up @@ -385,6 +393,7 @@ void responseContainsSearchSlipsForRequestsOfTypeHoldOnly() {
@ParameterizedTest
@EnumSource(value = SlipsType.class)
void responseIncludesItemsFromDifferentLocationsForSameServicePoint(SlipsType slipsType) {
configurationsFixture.configurePrintHoldRequests(true);
UUID circDesk1 = servicePointsFixture.cd1().getId();

// Circ desk 1: Second floor
Expand Down Expand Up @@ -440,6 +449,7 @@ void responseIncludesItemsFromDifferentLocationsForSameServicePoint(SlipsType sl
@ParameterizedTest
@EnumSource(value = SlipsType.class)
void responseDoesNotIncludeSlipsFromDifferentServicePoint(SlipsType slipsType) {
configurationsFixture.configurePrintHoldRequests(true);
UUID circDesk1 = servicePointsFixture.cd1().getId();
UUID circDesk4 = servicePointsFixture.cd4().getId();

Expand Down Expand Up @@ -503,6 +513,7 @@ void responseDoesNotIncludeSlipsFromDifferentServicePoint(SlipsType slipsType) {
@ParameterizedTest
@EnumSource(value = SlipsType.class)
void responseContainsSlipsWhenServicePointHasManyLocations(SlipsType slipsType) {
configurationsFixture.configurePrintHoldRequests(true);
final UUID servicePointId = servicePointsFixture.cd1().getId();
final int numberOfLocations = 100;

Expand Down Expand Up @@ -546,6 +557,7 @@ void responseContainsSlipsWhenServicePointHasManyLocations(SlipsType slipsType)

@Test
void responseContainsSearchSlipsForTLR() {
configurationsFixture.configurePrintHoldRequests(true);
settingsFixture.enableTlrFeature();
var servicePointId = servicePointsFixture.cd1().getId();
var steve = usersFixture.steve();
Expand Down Expand Up @@ -574,6 +586,7 @@ void responseContainsSearchSlipsForTLR() {

@Test
void responseContainsSearchSlipsForQueueTLRs() {
configurationsFixture.configurePrintHoldRequests(true);
settingsFixture.enableTlrFeature();
var servicePointId = servicePointsFixture.cd1().getId();
var steve = usersFixture.steve();
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/api/support/APITests.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import api.support.fixtures.CirculationItemsFixture;
import api.support.fixtures.CirculationRulesFixture;
import api.support.fixtures.ClaimItemReturnedFixture;
import api.support.fixtures.ConfigurationsFixture;
import api.support.fixtures.DeclareLostFixtures;
import api.support.fixtures.DepartmentFixture;
import api.support.fixtures.EndPatronSessionClient;
Expand Down Expand Up @@ -303,6 +304,7 @@ public abstract class APITests {
protected final DepartmentFixture departmentFixture = new DepartmentFixture();
protected final CheckOutLockFixture checkOutLockFixture = new CheckOutLockFixture();
protected final SettingsFixture settingsFixture = new SettingsFixture();
protected final ConfigurationsFixture configurationsFixture = new ConfigurationsFixture(configClient);
protected final SearchInstanceFixture searchFixture = new SearchInstanceFixture();

protected APITests() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package api.support.builders;

import io.vertx.core.json.JsonObject;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.With;

@With
@AllArgsConstructor
@NoArgsConstructor(force = true)
public class PrintHoldRequestConfigurationBuilder extends JsonBuilder implements Builder {

private final boolean printHoldRequestsEnabled;

@Override
public JsonObject create() {
JsonObject request = new JsonObject();
request.put("printHoldRequestsEnabled", printHoldRequestsEnabled);
return request;
}
}
9 changes: 9 additions & 0 deletions src/test/java/api/support/fixtures/ConfigurationExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.folio.circulation.support.json.JsonPropertyWriter.write;

import api.support.builders.ConfigRecordBuilder;
import api.support.builders.PrintHoldRequestConfigurationBuilder;
import io.vertx.core.json.JsonObject;

public class ConfigurationExample {
Expand Down Expand Up @@ -37,6 +38,14 @@ public static ConfigRecordBuilder schedulerNoticesLimitConfiguration(String limi
DEFAULT_NOTIFICATION_SCHEDULER_CONFIG_NAME, limit);
}

public static ConfigRecordBuilder setPrintHoldRequestsEnabled(boolean enabled) {
return new ConfigRecordBuilder("SETTINGS", "PRINT_HOLD_REQUESTS",
new PrintHoldRequestConfigurationBuilder()
.withPrintHoldRequestsEnabled(enabled)
.create()
.encodePrettily());
}

private static JsonObject combinedTimeZoneConfig(String timezone) {
final JsonObject encodedValue = new JsonObject();
write(encodedValue, "locale", US_LOCALE);
Expand Down
27 changes: 27 additions & 0 deletions src/test/java/api/support/fixtures/ConfigurationsFixture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package api.support.fixtures;

import api.support.http.ResourceClient;

import java.util.UUID;

public class ConfigurationsFixture {
private final ResourceClient client;
private UUID printHoldRequestConfigurationEntryId = null;

public ConfigurationsFixture(ResourceClient client) {
this.client = client;
}

public void configurePrintHoldRequests(boolean printHoldRequestsEnabled) {
deletePrintHoldRequestConfig();
printHoldRequestConfigurationEntryId = client.create(
ConfigurationExample.setPrintHoldRequestsEnabled(printHoldRequestsEnabled)).getId();
}

public void deletePrintHoldRequestConfig() {
if (printHoldRequestConfigurationEntryId != null) {
client.delete(printHoldRequestConfigurationEntryId);
printHoldRequestConfigurationEntryId = null;
}
}
}