Destination cache in Approuter and Connectivity
Connectivity in @sap-cloud-sdk
TL;DR
- Built-in cache mechanism with
useCache
in option - By default expiration time is 5 mins and no eviction
By default, if we use executeHttpRequest
from @sap-cloud-sdk/http-client
, the function signature is:
function executeHttpRequest<T extends HttpRequestConfig>(destination: DestinationOrFetchOptions, requestConfig: T, options?: HttpRequestOptions): Promise<HttpResponse>;
The first arg accepts a Destination
or DestinationFetchOptions
, currently in our system, we always use DestinationFetchOptions
.
Before http-client
perform request, it will first try to resolve destination by options, the detailed implementation sequential flow looks like below:
destination-accessor.getDestination
actually will not call getDestinationFromDestinationService only, in the above diagram it’s just simplified for better understanding, here is the detailed code logic:
async function getDestination(options) {
const destination = (0, destination_from_env_1.searchEnvVariablesForDestination)(options) ||
(await (0, destination_from_registration_1.searchRegisteredDestination)(options)) ||
(await (0, destination_from_vcap_1.searchServiceBindingForDestination)(options)) ||
(await (0, destination_from_service_1.getDestinationFromDestinationService)(options));
return destination;
}
destination-cache
underlying is using cache
with fixed 5 mins as expiration time, however, please note that the in-memory cache implementation does not support eviction, so it’s important to keep in mind not to cache objects unlimitedly, otherwise it may cause OOM.
Approuter in @sap
TL;DR
- NO global cache, only user session level cache
- No option to enable/disable cache for destination in
xs-app.json
- Destination Service in PROD has near half request come from approuter
approuter
is using a totally different approach to retrieve destination as above, here is the simplified sequential diagram:
destination-token-middleware.getCacheDestination
is getting cached destination from user session, here is the code:
function getCachedDestination(req, key, destinationName){
let destination = req.session && req.session.user && req.session.user.destinations && req.session.user.destinations[key];
if (destination && ((destination.destinationConfiguration.authentication === 'BasicAuthentication'
|| destination.destinationConfiguration.authentication === 'NoAuthentication') ||
(destination.expireDate && destination.expireDate - Date.now() > 0))){
const logger = req.loggingContext.getLogger('/Destination service');
logger.info('Destination ' + destinationName + ' has been retrieved from cache');
return destination;
} else {
return null;
}
}
Despite this, there is no other place in the request flow will cache the destination instance currently, which means each request from different user will result in a call to DestinationService, thus we did a check of backtrace in dynatrace, and found that the result proved the assumption:
BackTrace for DestinationService in DEV:
BackTrace for DestinationService in PROD:
More findings
Approuter supports integrate with HTML5 Application Repository
, where we can change routes dynamically in runtime without redeploy approuter to make changes on xs-app.json
work, the configuration supports global cache and by default cache expiration time is 5 mins. Detailed logic can be found in dynamic-routing-util
, documentation can be found in @sap/approuter - README.md
.
For schema of xs-app.json
we can find from xs-app-schema.json
.