Skip to content

Commit

Permalink
To avoid sending request on every page load, instead create an api ro…
Browse files Browse the repository at this point in the history
…ute to handle caching. If key with the calculated epoch does not exists, fetch data and save it to cache (Redis) and set key expiration to 30 minutes (check for new data every 30 minutes), if exists get data from cache.
  • Loading branch information
morsellif committed Mar 6, 2024
1 parent 7e01dc7 commit f55282c
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 26 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
UPSTASH_REDIS_REQUEST_URL=
UPSTASH_REDIS_REST_TOKEN=
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
"vue-tsc": "^2.0.2"
},
"dependencies": {
"@upstash/redis": "^1.28.4",
"date-fns": "^3.3.1",
"nuxt": "^3.10.3",
"vue": "^3.4.19",
"vue-router": "^4.3.0"
Expand Down
11 changes: 1 addition & 10 deletions src/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,7 @@ const backInTime = () => {
return currentDate;
};
const { data } = useFetch<NoTimeResponse>(
() =>
'https://allertameteo.regione.emilia-romagna.it/o/api/allerta/get-sensor-values-no-time',
{
query: {
variabile: '254,0,0/1,-,-,-/B13215',
time: backInTime().getTime(),
},
},
);
const { data } = useFetch<NoTimeResponse>('/api/stations');
if (data) {
time.value = data.value?.shift() as Time;
Expand Down
66 changes: 50 additions & 16 deletions src/server/api/stations.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,58 @@
const backInTime = () => {
import { addHours } from 'date-fns';

import { redis, keyParser, isCaching } from './../../utils/redis';

const currentHourUTCEpoch = () => {
const currentDate = new Date();
currentDate.setHours(currentDate.getHours() - 1);
currentDate.setMinutes(0);
currentDate.setSeconds(0);
currentDate.setMilliseconds(0);
if (currentDate.getMinutes() <= 30) {
currentDate.setMinutes(30, 0, 0);
} else {
addHours(currentDate, 1);
currentDate.setMinutes(0, 0, 0);
}

return currentDate;
return currentDate.getTime();
};

export default defineEventHandler(async (_event) => {
const data = await $fetch<NoTimeResponse>(
'https://allertameteo.regione.emilia-romagna.it/o/api/allerta/get-sensor-values-no-time',
{
method: 'GET',
query: {
variabile: '254,0,0/1,-,-,-/B13215',
time: backInTime().getTime(),
// get the latest most complete stations data
const epoch = currentHourUTCEpoch().toString();

const fromCache = isCaching()
? await redis.get<string>(keyParser(epoch))
: null;
if (!fromCache) {
console.log('Data not found in cache...');
console.log('Fetching new data...');
const data = await $fetch<NoTimeResponse>(
'https://allertameteo.regione.emilia-romagna.it/o/api/allerta/get-sensor-values-no-time',
{
method: 'POST',
query: {
variabile: '254,0,0/1,-,-,-/B13215',
time: epoch,
},
params: {
ts: epoch,
latestAvailabelTimeIsKnown: 'false',
time: epoch,
},
},
},
);
);

if (isCaching()) {
// using transaction to optimize Redis server calls
const transaction = redis.multi();
transaction.set(keyParser(epoch), JSON.stringify(data));
transaction.expire(keyParser(epoch), 30 * 60);

console.log('Saving new data to cache...');
const _result = await transaction.exec();
}

return data;
return data;
} else {
console.log('Data found in cache...');
return fromCache;
}
});
29 changes: 29 additions & 0 deletions src/utils/redis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Redis } from '@upstash/redis';

const UPSTASH_REDIS_REQUEST_URL = process.env.UPSTASH_REDIS_REQUEST_URL;
const UPSTASH_REDIS_REST_TOKEN = process.env.UPSTASH_REDIS_REST_TOKEN;
const REDIS_PREFIX = process.env.REDIS_PREFIX || 'LOCALDEV';

if (!UPSTASH_REDIS_REQUEST_URL) {
console.warn(
'You have not configured `UPSTASH_REDIS_REQUEST_URL` env variable',
);
console.warn('Request caching could not be enabled.');
}

if (!UPSTASH_REDIS_REST_TOKEN) {
console.warn(
'You have not configured `UPSTASH_REDIS_REST_TOKEN` env variable.',
);
console.warn('Request caching could not be enabled.');
}

export const isCaching = () =>
UPSTASH_REDIS_REQUEST_URL && UPSTASH_REDIS_REST_TOKEN;

export const redis = new Redis({
url: UPSTASH_REDIS_REQUEST_URL || 'NO_URL',
token: UPSTASH_REDIS_REST_TOKEN || 'NO_TOKEN',
});

export const keyParser = (key: string) => `${key}_${REDIS_PREFIX}`;

0 comments on commit f55282c

Please sign in to comment.