Skip to content

Commit

Permalink
Merge branch 'master' into tmp-release-v12.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
azizbekxm authored Oct 31, 2024
2 parents 57204c1 + 5936db1 commit a663065
Show file tree
Hide file tree
Showing 21 changed files with 613 additions and 163 deletions.
3 changes: 3 additions & 0 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
"invoice.invoice-lines.collection.get",
"finance.transactions.collection.get",
"finance.exchange-rate.item.get",
"finance.fiscal-years.item.get",
"finance.fiscal-years.collection.get",
"finance.funds.item.get",
"finance.funds.collection.get",
"finance.ledgers.current-fiscal-year.item.get",
Expand Down Expand Up @@ -848,6 +850,7 @@
"inventory-storage.instance-statuses.collection.get",
"inventory-storage.contributor-name-types.collection.get",
"user-tenants.collection.get",
"configuration.entries.collection.get",
"consortia.sharing-instances.item.post",
"acquisitions-units-storage.units.collection.get",
"acquisitions-units-storage.memberships.collection.get"
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/org/folio/config/ApplicationConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ OrganizationService organizationService(RestClient restClient) {
}

@Bean
FiscalYearService fiscalYearService(RestClient restClient, FundService fundService) {
return new FiscalYearService(restClient, fundService);
FiscalYearService fiscalYearService(RestClient restClient, FundService fundService, ConfigurationEntriesCache configurationEntriesCache) {
return new FiscalYearService(restClient, fundService, configurationEntriesCache);
}

@Bean
Expand Down Expand Up @@ -424,8 +424,9 @@ HoldingsSummaryService holdingsSummaryService(PurchaseOrderStorageService purcha
}

@Bean
CompositeOrderDynamicDataPopulateService totalExpendedPopulateService(TransactionService transactionService, InvoiceService invoiceService, InvoiceLineService invoiceLineService) {
return new CompositeOrderTotalFieldsPopulateService(transactionService, invoiceService, invoiceLineService);
CompositeOrderDynamicDataPopulateService totalExpendedPopulateService(TransactionService transactionService, InvoiceService invoiceService,
InvoiceLineService invoiceLineService, FiscalYearService fiscalYearService) {
return new CompositeOrderTotalFieldsPopulateService(transactionService, invoiceService, invoiceLineService, fiscalYearService);
}

@Bean("orderLinesSummaryPopulateService")
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/org/folio/orders/utils/CacheUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.folio.orders.utils;

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.vertx.core.Context;
import io.vertx.core.Vertx;

import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

public class CacheUtils {

public static <K, V> AsyncCache<K, V> buildAsyncCache(Vertx vertx, long cacheExpirationTime) {
return buildAsyncCache(task -> vertx.runOnContext(v -> task.run()), cacheExpirationTime);
}

public static <K, V> AsyncCache<K, V> buildAsyncCache(Context context, long cacheExpirationTime) {
return buildAsyncCache(task -> context.runOnContext(v -> task.run()), cacheExpirationTime);
}

private static <K, V> AsyncCache<K, V> buildAsyncCache(Executor executor, long cacheExpirationTime) {
return Caffeine.newBuilder()
.expireAfterWrite(cacheExpirationTime, TimeUnit.SECONDS)
.executor(executor)
.buildAsync();
}

private CacheUtils() {}

}
4 changes: 4 additions & 0 deletions src/main/java/org/folio/orders/utils/HelperUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -440,4 +440,8 @@ public interface FunctionReturningFuture<I, O> {
Future<O> apply(I item);
}

public interface BiFunctionReturningFuture<I1, I2, O> {
Future<O> apply(I1 item1, I2 item2);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import java.util.Map;
import java.util.stream.Collectors;

import static org.folio.rest.RestConstants.PATH_PARAM_PLACE_HOLDER;

public class ResourcePathResolver {

private ResourcePathResolver() {
Expand Down Expand Up @@ -49,6 +47,8 @@ private ResourcePathResolver() {
public static final String CONFIGURATION_ENTRIES = "configurations.entries";
public static final String LEDGER_FY_ROLLOVERS = "finance.ledger-rollovers";
public static final String LEDGER_FY_ROLLOVER_ERRORS = "finance.ledger-rollovers-errors";
public static final String LEDGER_CURRENT_FISCAL_YEAR = "finance.ledger.current-fiscal-year";
public static final String FISCAL_YEARS = "finance.fiscal-years";
public static final String ORDER_INVOICE_RELATIONSHIP = "order-invoice-relationship";
public static final String EXPORT_HISTORY = "export-history";
public static final String TAGS = "tags";
Expand Down Expand Up @@ -96,11 +96,13 @@ private ResourcePathResolver() {
apis.put(CONFIGURATION_ENTRIES, "/configurations/entries");
apis.put(LEDGER_FY_ROLLOVERS, "/finance/ledger-rollovers");
apis.put(LEDGER_FY_ROLLOVER_ERRORS, "/finance/ledger-rollovers-errors");
apis.put(LEDGER_CURRENT_FISCAL_YEAR, "/finance/ledgers/{id}/current-fiscal-year");
apis.put(FISCAL_YEARS, "/finance/fiscal-years");
apis.put(ORDER_INVOICE_RELATIONSHIP, "/orders-storage/order-invoice-relns");
apis.put(EXPORT_HISTORY, "/orders-storage/export-history");
apis.put(TAGS, "/tags");
apis.put(USERS, "/users");
apis.put(CONSORTIA_USER_TENANTS, "/consortia/" + PATH_PARAM_PLACE_HOLDER + "/user-tenants");
apis.put(CONSORTIA_USER_TENANTS, "/consortia/{id}/user-tenants");
apis.put(ORDER_SETTINGS, "/orders-storage/settings");
apis.put(ROUTING_LISTS, "/orders-storage/routing-lists");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,49 @@
package org.folio.service.caches;

import static org.folio.orders.utils.CacheUtils.buildAsyncCache;
import static org.folio.orders.utils.HelperUtils.SYSTEM_CONFIG_MODULE_NAME;
import static org.folio.service.configuration.ConfigurationEntriesService.CONFIG_QUERY;
import static org.folio.service.configuration.ConfigurationEntriesService.TENANT_CONFIGURATION_ENTRIES;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import io.vertx.core.Vertx;
import lombok.extern.log4j.Log4j2;
import org.folio.orders.utils.HelperUtils.BiFunctionReturningFuture;
import org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters;
import org.folio.rest.core.models.RequestContext;
import org.folio.rest.core.models.RequestEntry;
import org.folio.rest.tools.utils.TenantTool;
import org.folio.service.UserService;
import org.folio.service.configuration.ConfigurationEntriesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;

@Log4j2
@Component
public class ConfigurationEntriesCache {
private static final Logger log = LogManager.getLogger();

private static final String UNIQUE_CACHE_KEY_PATTERN = "%s_%s_%s";
@Value("${orders.cache.configuration-entries.expiration.time.seconds:30}")
private long cacheExpirationTime;

private final AsyncCache<String, JsonObject> configsCache;
private final AsyncCache<String, String> systemCurrencyCache;
private static final String UNIQUE_CACHE_KEY_PATTERN = "%s_%s_%s";
private final AsyncCache<String, String> systemTimezoneCache;
private final ConfigurationEntriesService configurationEntriesService;


@Autowired
public ConfigurationEntriesCache(ConfigurationEntriesService configurationEntriesService) {
this.configurationEntriesService = configurationEntriesService;
configsCache = Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS)
.executor(task -> Vertx.currentContext()
.runOnContext(v -> task.run()))
.buildAsync();

systemCurrencyCache = Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS)
.executor(task -> Vertx.currentContext()
.runOnContext(v -> task.run()))
.buildAsync();
var context = Vertx.currentContext();
configsCache = buildAsyncCache(context, cacheExpirationTime);
systemCurrencyCache = buildAsyncCache(context, cacheExpirationTime);
systemTimezoneCache = buildAsyncCache(context, cacheExpirationTime);
}

/**
Expand All @@ -55,25 +52,28 @@ public ConfigurationEntriesCache(ConfigurationEntriesService configurationEntrie
* @return CompletableFuture with {@link String} ISBN UUID value
*/
public Future<JsonObject> loadConfiguration(String module, RequestContext requestContext) {
try {
RequestEntry requestEntry = new RequestEntry(TENANT_CONFIGURATION_ENTRIES)
.withQuery(String.format(CONFIG_QUERY, module))
.withOffset(0)
.withLimit(Integer.MAX_VALUE);
return loadConfigurationData(module, requestContext, configsCache, configurationEntriesService::loadConfiguration);
}

var cacheKey = buildUniqueKey(requestEntry, requestContext);
public Future<String> getSystemCurrency(RequestContext requestContext) {
return loadConfigurationData(SYSTEM_CONFIG_MODULE_NAME, requestContext, systemCurrencyCache, configurationEntriesService::getSystemCurrency);
}

return Future.fromCompletionStage(configsCache.get(cacheKey, (key, executor) -> loadConfiguration(requestEntry, requestContext)));
} catch (Exception e) {
log.error("loadConfiguration:: Error loading tenant configuration from cache, tenantId: '{}'", TenantTool.tenantId(requestContext.getHeaders()), e);
return Future.failedFuture(e);
}
public Future<String> getSystemTimeZone(RequestContext requestContext) {
return loadConfigurationData(SYSTEM_CONFIG_MODULE_NAME, requestContext, systemTimezoneCache, configurationEntriesService::getSystemTimeZone);
}

private CompletableFuture<JsonObject> loadConfiguration(RequestEntry requestEntry, RequestContext requestContext) {
return configurationEntriesService.loadConfiguration(requestEntry, requestContext)
.toCompletionStage()
.toCompletableFuture();
private <T> Future<T> loadConfigurationData(String module, RequestContext requestContext, AsyncCache<String, T> cache,
BiFunctionReturningFuture<RequestEntry, RequestContext, T> configExtractor) {
var requestEntry = new RequestEntry(TENANT_CONFIGURATION_ENTRIES)
.withQuery(String.format(CONFIG_QUERY, module))
.withOffset(0)
.withLimit(Integer.MAX_VALUE);
var cacheKey = buildUniqueKey(requestEntry, requestContext);
return Future.fromCompletionStage(cache.get(cacheKey, (key, executor) ->
configExtractor.apply(requestEntry, requestContext)
.onFailure(t -> log.error("Error loading tenant configuration, tenantId: '{}'", TenantTool.tenantId(requestContext.getHeaders()), t))
.toCompletionStage().toCompletableFuture()));
}

private String buildUniqueKey(RequestEntry requestEntry, RequestContext requestContext) {
Expand All @@ -83,25 +83,4 @@ private String buildUniqueKey(RequestEntry requestEntry, RequestContext requestC
return String.format(UNIQUE_CACHE_KEY_PATTERN, tenantId, userId, endpoint);
}

public Future<String> getSystemCurrency(RequestContext requestContext) {

try {
RequestEntry requestEntry = new RequestEntry(TENANT_CONFIGURATION_ENTRIES)
.withQuery(String.format(CONFIG_QUERY, SYSTEM_CONFIG_MODULE_NAME))
.withOffset(0)
.withLimit(Integer.MAX_VALUE);

var cacheKey = buildUniqueKey(requestEntry, requestContext);

return Future.fromCompletionStage(systemCurrencyCache.get(cacheKey, (key, executor) -> getSystemCurrency(requestEntry, requestContext)));
} catch (Exception e) {
log.warn("get:: Error loading system currency from cache, tenantId: '{}'", TenantTool.tenantId(requestContext.getHeaders()), e);
return Future.failedFuture(e);
}
}
private CompletableFuture<String> getSystemCurrency(RequestEntry requestEntry, RequestContext requestContext) {
return configurationEntriesService.getSystemCurrency(requestEntry, requestContext)
.toCompletionStage()
.toCompletableFuture();
}
}
18 changes: 5 additions & 13 deletions src/main/java/org/folio/service/caches/InventoryCache.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.folio.service.caches;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -14,12 +13,13 @@
import org.springframework.stereotype.Component;

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;

import static org.folio.orders.utils.CacheUtils.buildAsyncCache;

@Component
public class InventoryCache {
private static final Logger log = LogManager.getLogger();
Expand All @@ -37,17 +37,9 @@ public class InventoryCache {

public InventoryCache(InventoryService inventoryService) {
this.inventoryService = inventoryService;
asyncCache = Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS)
.executor(task -> Vertx.currentContext()
.runOnContext(v -> task.run()))
.buildAsync();

asyncJsonCache = Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS)
.executor(task -> Vertx.currentContext()
.runOnContext(v -> task.run()))
.buildAsync();
var context = Vertx.currentContext();
asyncCache = buildAsyncCache(context, 30);
asyncJsonCache = buildAsyncCache(context, 30);
}

public Future<String> getISBNProductTypeId(RequestContext requestContext) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.folio.service.caches;

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpMethod;
Expand All @@ -15,7 +14,8 @@
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import static org.folio.orders.utils.CacheUtils.buildAsyncCache;

/**
* An in-memory cache that stores total amount of imported records
Expand All @@ -38,10 +38,7 @@ public class JobExecutionTotalRecordsCache {

@Autowired
public JobExecutionTotalRecordsCache(Vertx vertx) {
cache = Caffeine.newBuilder()
.expireAfterAccess(cacheExpirationTime, TimeUnit.SECONDS)
.executor(task -> vertx.runOnContext(v -> task.run()))
.buildAsync();
cache = buildAsyncCache(vertx, cacheExpirationTime);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
Expand All @@ -15,13 +14,14 @@
import org.springframework.stereotype.Component;

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.Json;

import static org.folio.orders.utils.CacheUtils.buildAsyncCache;

@Component
public class JobProfileSnapshotCache {

Expand All @@ -34,10 +34,7 @@ public class JobProfileSnapshotCache {

@Autowired
public JobProfileSnapshotCache(Vertx vertx) {
cache = Caffeine.newBuilder()
.expireAfterAccess(cacheExpirationTime, TimeUnit.SECONDS)
.executor(task -> vertx.runOnContext(v -> task.run()))
.buildAsync();
cache = buildAsyncCache(vertx, cacheExpirationTime);
}

public Future<Optional<ProfileSnapshotWrapper>> get(String profileSnapshotId, OkapiConnectionParams params) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.folio.service.caches;

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpMethod;
Expand Down Expand Up @@ -48,10 +47,10 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import static java.lang.String.format;
import static org.folio.orders.utils.CacheUtils.buildAsyncCache;
import static org.folio.orders.utils.QueryUtils.encodeQuery;
import static org.folio.rest.RestConstants.ID;
import static org.folio.orders.utils.HelperUtils.collectResultsOnSuccess;
Expand Down Expand Up @@ -93,10 +92,7 @@ public MappingParametersCache(Vertx vertx, RestClient restClient,
AcquisitionsUnitsService acquisitionsUnitsService,
AcquisitionMethodsService acquisitionMethodsService) {
LOGGER.info("MappingParametersCache:: settings limit: '{}'", settingsLimit);
cache = Caffeine.newBuilder()
.expireAfterAccess(cacheExpirationTime, TimeUnit.SECONDS)
.executor(task -> vertx.runOnContext(v -> task.run()))
.buildAsync();
cache = buildAsyncCache(vertx, cacheExpirationTime);
this.restClient = restClient;
this.acquisitionsUnitsService = acquisitionsUnitsService;
this.acquisitionMethodsService = acquisitionMethodsService;
Expand Down
Loading

0 comments on commit a663065

Please sign in to comment.