com.sap.cds.mt.CdsDataStoreLookup Maven / Gradle / Ivy
/*
* ----------------------------------------------------------------
* © 2019-2021 SAP SE or an SAP affiliate company. All rights reserved.
* ----------------------------------------------------------------
*
*/
package com.sap.cds.mt;
import com.google.common.base.Ticker;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.sap.cds.CdsDataStoreConnector;
import com.sap.cds.CdsException;
import com.sap.cds.mtx.CdsDataStoreConnectorCreator;
import com.sap.cds.mtx.impl.CacheParams;
import com.sap.cds.reflect.CdsModel;
import java.util.function.BiPredicate;
import java.util.function.Function;
/**
* Responsible for retrieval of {@code CdsDataStoreConnectors}. For performance reasons {@code CdsDataStore}
* connector instances are cached per tenant. The cache is synchronized with the {@code MetaDataAccessor}'s cache:
* cache {@code CdsDataStore} entries are automatically refreshed when a cached model changes in
* the {@code MetaDataAccessor}'s cache. To manually refresh a {@code CdsDataStore}
* for a particular tenant the tenant's model must be refreshed or evicted at the {@code MetaDataAccessor}.
*
* @see com.sap.cds.mtx.MetaDataAccessor#refresh(String)
* @see com.sap.cds.mtx.MetaDataAccessor#evict(String)
*/
public class CdsDataStoreLookup {
private final BiPredicate isModelOutDated;
private final LoadingCache tenantToConnector;
/**
* @param cdsDataStoreConnectorCreator factory that creates a
* {@link CdsDataStoreConnector}
* @param isModelOutDated predicate that takes the tenant id and
* the current model as input and decides if
* the model is out dated
* @param cacheParams Parameters that control cache lifecycle
* @param cacheTicker Optional ticker used by guava cache for
* testing purposes, use null for productive
* use
*/
public CdsDataStoreLookup(CdsDataStoreConnectorCreator cdsDataStoreConnectorCreator,
BiPredicate isModelOutDated, CacheParams cacheParams, Ticker cacheTicker) {
this.isModelOutDated = isModelOutDated;
this.tenantToConnector = buildCache(cacheParams, cacheTicker, cdsDataStoreConnectorCreator::create);
}
/**
* Determine a data store connector for a tenant
*
* @param tenantId tenant identifier
* @return a CDS data store connector
*/
public CdsDataStoreConnector getCdsDataStoreConnector(String tenantId) throws CdsException {
try {
return tenantToConnector.getUnchecked(tenantId);
} catch (UncheckedExecutionException e) {
throw new CdsException(e);
}
}
public void evictIfOutDated(String tenantId) {
CdsDataStoreConnector connector = getCdsDataStoreConnector(tenantId);
if (connector != null) {
CdsModel cdsModel = connector.reflect();
if (isModelOutDated.test(tenantId, cdsModel)) {
tenantToConnector.invalidate(tenantId);
}
}
}
private static LoadingCache buildCache(CacheParams params, Ticker cacheTicker,
Function loader) {
CacheBuilder