Skip to content
Open
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
16 changes: 14 additions & 2 deletions src/main/java/org/folio/rest/impl/OrdersSettingsAPI.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package org.folio.rest.impl;

import static io.vertx.core.json.JsonObject.mapFrom;

import java.util.Map;

import javax.ws.rs.core.Response;

import org.folio.rest.annotations.Validate;
import org.folio.rest.core.BaseApi;
import org.folio.rest.jaxrs.model.Setting;
import org.folio.rest.jaxrs.resource.OrdersStorageSettings;
import org.folio.rest.persist.HelperUtils;
import org.folio.services.setting.SettingService;
import org.folio.spring.SpringContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -16,7 +20,7 @@
import io.vertx.core.Handler;
import io.vertx.core.Vertx;

public class OrdersSettingsAPI implements OrdersStorageSettings {
public class OrdersSettingsAPI extends BaseApi implements OrdersStorageSettings {

@Autowired
private SettingService settingService;
Expand All @@ -29,7 +33,10 @@ public OrdersSettingsAPI() {
@Validate
public void getOrdersStorageSettings(String query, String totalRecords, int offset, int limit, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
settingService.getSettings(query, offset, limit, okapiHeaders, asyncResultHandler, vertxContext);
settingService.getSettings(query, offset, limit, okapiHeaders, vertxContext)
.onComplete(ar -> asyncResultHandler.handle(ar.succeeded()
? buildOkResponse(ar.result())
: buildErrorResponse(ar.cause())));
}

@Override
Expand Down Expand Up @@ -60,5 +67,10 @@ public void deleteOrdersStorageSettingsById(String id, Map<String, String> okapi
settingService.deleteSetting(id, okapiHeaders, asyncResultHandler, vertxContext);
}

@Override
protected String getEndpoint(Object entity) {
return HelperUtils.getEndpoint(OrdersStorageSettings.class) + mapFrom(entity).getString("id");
}

}

41 changes: 18 additions & 23 deletions src/main/java/org/folio/services/setting/SettingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import javax.ws.rs.core.Response;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.folio.rest.jaxrs.model.Setting;
import org.folio.rest.jaxrs.model.SettingCollection;
import org.folio.rest.jaxrs.resource.OrdersStorageSettings;
import org.folio.rest.jaxrs.resource.OrdersStorageSettings.GetOrdersStorageSettingsResponse;
import org.folio.rest.persist.PgUtil;
import org.folio.rest.tools.utils.TenantTool;
import org.folio.services.setting.util.SettingKey;
Expand All @@ -37,9 +38,9 @@ public class SettingService {

private static final String SETTINGS_TABLE = "settings";
private static final String SETTINGS_BY_KEY_QUERY = "key==%s";
private static final String SETTINGS_CACHE_KEY = "%s.%s";
private static final String SETTINGS_CACHE_KEY = "%s.%s.%s.%s";

private AsyncCache<String, Optional<Setting>> asyncCache;
private AsyncCache<String, SettingCollection> asyncCache;

@Value("${orders-storage.cache.setting-data.expiration.time.seconds:60}")
private long cacheExpirationTime;
Expand All @@ -53,33 +54,27 @@ void init() {
}

public Future<Optional<Setting>> getSettingByKey(SettingKey settingKey, Map<String, String> okapiHeaders, Context vertxContext) {
return getSettings(SETTINGS_BY_KEY_QUERY.formatted(settingKey.getName()), 0, 1, okapiHeaders, vertxContext)
.map(SettingService::extractSettingIfExistsAndIsUnique);
}

public Future<SettingCollection> getSettings(String query, int offset, int limit, Map<String, String> okapiHeaders, Context vertxContext) {
if (StringUtils.isBlank(query)) {
return getSettingsCollection(query, offset, limit, okapiHeaders, vertxContext);
}
try {
var settingCacheKey = String.format(SETTINGS_CACHE_KEY, TenantTool.tenantId(okapiHeaders), settingKey.getName());
var settingCacheKey = SETTINGS_CACHE_KEY.formatted(TenantTool.tenantId(okapiHeaders), query, offset, limit);
return Future.fromCompletionStage(asyncCache.get(settingCacheKey, (key, executor) ->
getSettingByKeyFromDB(settingKey, okapiHeaders, vertxContext)));
getSettingsCollection(query, offset, limit, okapiHeaders, vertxContext).toCompletionStage().toCompletableFuture()));
} catch (Exception e) {
log.error("Error when retrieving setting with key: '{}'", settingKey.getName(), e);
log.error("Error when retrieving settings by query: '{}'", query, e);
return Future.failedFuture(e);
}
}

private CompletableFuture<Optional<Setting>> getSettingByKeyFromDB(SettingKey settingKey, Map<String, String> okapiHeaders, Context vertxContext) {
var query = String.format(SETTINGS_BY_KEY_QUERY, settingKey.getName());
return getSettings(query, 0, 1, okapiHeaders, vertxContext)
.map(response -> convertResponseToEntity(response, SettingCollection.class))
.map(SettingService::extractSettingIfExistsAndIsUnique)
.toCompletionStage().toCompletableFuture();
}

public void getSettings(String query, int offset, int limit, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
getSettings(query, offset, limit, okapiHeaders, vertxContext)
.onComplete(asyncResultHandler);
}

public Future<Response> getSettings(String query, int offset, int limit, Map<String, String> okapiHeaders, Context vertxContext) {
return PgUtil.get(SETTINGS_TABLE, Setting.class, SettingCollection.class, query, offset, limit, okapiHeaders, vertxContext,
OrdersStorageSettings.GetOrdersStorageSettingsResponse.class);
private Future<SettingCollection> getSettingsCollection(String query, int offset, int limit, Map<String, String> okapiHeaders, Context vertxContext) {
return PgUtil.get(SETTINGS_TABLE, Setting.class, SettingCollection.class, query, offset, limit, okapiHeaders, vertxContext, GetOrdersStorageSettingsResponse.class)
.compose(response -> convertResponseToEntity(response, SettingCollection.class));
}

public void createSetting(Setting entity, Map<String, String> okapiHeaders,
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/org/folio/util/DbUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;

import org.apache.commons.collections4.IteratorUtils;
import org.folio.HttpStatus;
import org.folio.rest.persist.Conn;
import org.folio.rest.persist.Criteria.Criterion;
import org.folio.rest.persist.DBClient;
Expand Down Expand Up @@ -72,12 +73,15 @@ public static long getRowSetAsCount(RowSet<Row> rowSet) {
.findFirst().orElse(0L);
}

public static <T> T convertResponseToEntity(Response response, Class<T> entityClass) {
public static <T> Future<T> convertResponseToEntity(Response response, Class<T> entityClass) {
if (response.getStatus() != HttpStatus.HTTP_OK.toInt()) {
return Future.failedFuture(new HttpException(response.getStatus(), response.getEntity().toString()));
}
try {
return JsonObject.mapFrom(response.getEntity()).mapTo(entityClass);
return Future.succeededFuture(JsonObject.mapFrom(response.getEntity()).mapTo(entityClass));
} catch (RuntimeException e) {
throw new IllegalStateException(String.format("Cannot convert response '%s' to entity '%s' - error message: %s",
response.getEntity(), entityClass.getName(), e.getMessage()));
return Future.failedFuture(new IllegalStateException(String.format("Cannot convert response '%s' to entity '%s' - error message: %s",
response.getEntity(), entityClass.getName(), e.getMessage())));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void initMocks() throws Exception {
void positive_shouldProcessInventoryCreate(String tenantId) {
var eventObject = createResourceEvent(DIKU_TENANT, CREATE);
var record = createKafkaRecord(eventObject, DIKU_TENANT);
doReturn(Future.succeededFuture(Response.ok(createSettingCollection(createSetting("true"))).build()))
doReturn(Future.succeededFuture(createSettingCollection(createSetting("true"))))
.when(settingService).getSettings(anyString(), anyInt(), anyInt(), anyMap(), any(Context.class));
doReturn(Future.succeededFuture(Optional.of(new ConsortiumConfiguration(tenantId, CONSORTIUM_ID))))
.when(consortiumConfigurationService).getConsortiumConfiguration(any());
Expand Down Expand Up @@ -118,7 +118,7 @@ void positive_shouldSkipInventoryCreateEventIfCentralOrderingIsDisabled() {
var eventObject = createResourceEvent(DIKU_TENANT, CREATE);
var record = createKafkaRecord(eventObject, DIKU_TENANT);
var emptySettings = new SettingCollection().withTotalRecords(0);
doReturn(Future.succeededFuture(Response.ok(emptySettings).build()))
doReturn(Future.succeededFuture(emptySettings))
.when(settingService).getSettings(anyString(), anyInt(), anyInt(), anyMap(), any(Context.class));
doReturn(Future.succeededFuture(Optional.of(new ConsortiumConfiguration(DIKU_TENANT, CONSORTIUM_ID))))
.when(consortiumConfigurationService).getConsortiumConfiguration(any());
Expand Down
Loading