Cache data using app state
In this guide, you'll learn how to use the app state to cache expensive requests to external systems.
Calls to external systems can be slow, or you might run into request throttling, or the system might be unavailable sometimes. When you use the app state to cache responses from external systems, the information will be available even when the external system isn't.
Code
Let's assume you have a function like the following, calling the API of an external system:
export default async function () {
const apiResponse = await fetch('https://swapi.dev/api/people/1/');
if (!apiResponse.ok) {
throw new Error();
}
return apiResponse.json();
}
If the response contains user-specific or sensitive information, use user app state to persist information.
You can call the function from your UI using the package @dynatrace-sdk/app-utils
.
If you want to cache the response, store the function's response using the app state via the package @dynatrace-sdk/client-state
.
To install both packages, run the following command:
npm install @dynatrace-sdk/app-utils @dynatrace-sdk/client-state
The following snippet combines the app state with the app function. We also use the validUntilTime
property since, typically, the app state should cache the data only for a limited time.
import { functions } from '@dynatrace-sdk/app-utils';
import { stateClient } from '@dynatrace-sdk/client-state';
export const callCachableFunction = async (functionName: string, appStateKey: string, validUntilTime: string) =>
stateClient
.getAppState({
key: appStateKey,
})
.then((appState) => {
// Saved app state found. Return the saved value as a JSON object
return JSON.parse(appState.value);
})
.catch(async (e) => {
// No app state found. Trigger the function, then store the response in the app state
const response = await functions.call(functionName);
const json = await response.json();
await stateClient.setAppState({
key: appStateKey,
body: {
validUntilTime,
value: JSON.stringify(json),
},
});
return json;
});
This operation requires the following scopes:
state:app-states:read
state:app-states:write
You can then use this helper with e.g. callCachableFunction("external-call", "swapi-people", "now+30d")
.
Summary
With these few lines of code, you can cache the response of an app function and improve the user experience in your app.
If you're looking for further ideas, check out Zod for typesafe data processing.