Add a time-based cache for the progress result from the API

This commit is contained in:
Rasmus Rasmussen 2024-12-17 10:46:10 +01:00
parent 1c74ae9de5
commit 3822339dd9
7 changed files with 112 additions and 34 deletions

View File

@ -1,8 +1,9 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2024-11-01',
compatibilityDate: '2024-12-16',
ssr: true,
devtools: { enabled: false },
devtools: { enabled: true },
css: ['@/assets/css/main.css'],
postcss: {
@ -12,5 +13,10 @@ export default defineNuxtConfig({
},
},
routeRules: {
"/": {isr: true},
"/progress": {isr: true},
},
modules: ['@nuxtjs/tailwindcss'],
})

View File

@ -7,6 +7,7 @@
"name": "nuxt-app",
"hasInstallScript": true,
"dependencies": {
"@nuxtjs/partytown": "^1.5.0",
"nuxt": "^3.14.1592",
"vue": "latest",
"vue-router": "latest"
@ -509,6 +510,18 @@
"node": ">=6.9.0"
}
},
"node_modules/@builder.io/partytown": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/@builder.io/partytown/-/partytown-0.10.2.tgz",
"integrity": "sha512-A9U+4PREWcS+CCYzKGIPovtGB/PBgnH/8oQyCE6Nr9drDJk6cMPpLQIEajpGPmG9tYF7N3FkRvhXm/AS9+0iKg==",
"license": "MIT",
"bin": {
"partytown": "bin/partytown.cjs"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@cloudflare/kv-asset-handler": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz",
@ -1451,6 +1464,19 @@
"vue": "^3.3.4"
}
},
"node_modules/@nuxtjs/partytown": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@nuxtjs/partytown/-/partytown-1.5.0.tgz",
"integrity": "sha512-3qJXEXoHydCEEiHZCy4Q80kHTqKD0T9Ryj8kjh0bwTfNHGQ5auC7pqJxy6+CFOqfZZRcGalqGb0MhhRc8GdTdw==",
"license": "MIT",
"dependencies": {
"@builder.io/partytown": "^0.10.0",
"@nuxt/kit": "^3.11.1",
"knitwork": "^1.0.0",
"serve-static": "^1.15.0",
"ufo": "^1.5.3"
}
},
"node_modules/@nuxtjs/tailwindcss": {
"version": "6.12.2",
"resolved": "https://registry.npmjs.org/@nuxtjs/tailwindcss/-/tailwindcss-6.12.2.tgz",

View File

@ -10,6 +10,7 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@nuxtjs/partytown": "^1.5.0",
"nuxt": "^3.14.1592",
"vue": "latest",
"vue-router": "latest"

View File

@ -1,12 +1,38 @@
<script setup lang="ts">
import getProgress from "~/plugins/getProgress";
import { fetchWithCache } from '~/utils/cacheUtil';
const data = ref<ProgressType | null>(null);
const loading = ref<boolean>(true);
const error = ref<string | null>(null);
const fetchMyData = async () => {
try {
loading.value = true;
// Use the caching utility
data.value = await fetchWithCache<ProgressType>(
'Progress',
async () => {
const response = await fetch('https://proxy.rbwr.dk/progress');
if (!response.ok) throw new Error('API fetch failed');
return (await response.json()) as ProgressType;
},
5 // Cache max age in seconds
);
} catch (err) {
error.value = (err as Error).message;
} finally {
loading.value = false;
}
};
fetchMyData();
const progress = getProgress();
</script>
<template>
<div class="h-screen grid place-items-center">
<div v-if="progress">
<div v-if="data">
<table class="table-auto border-gray-300">
<thead>
<tr>
@ -18,31 +44,31 @@ const progress = getProgress();
<tbody >
<tr>
<td class="px-4 py-2">Percentage of Ipv4 scanned</td>
<td class="px-4 py-2">{{progress.percentageOfIpv4Scanned}}</td>
<td class="px-4 py-2">{{data.percentageOfIpv4Scanned}}</td>
</tr>
<tr>
<td class="px-4 py-2">Total filtered</td>
<td class="px-4 py-2">{{progress.totalFiltered}}</td>
<td class="px-4 py-2">{{data.totalFiltered}}</td>
</tr>
<tr>
<td class="px-4 py-2">Total Discarded</td>
<td class="px-4 py-2">{{progress.totalDiscarded}}</td>
<td class="px-4 py-2">{{data.totalDiscarded}}</td>
</tr>
<tr>
<td class="px-4 py-2">Amount of Ipv4 left</td>
<td class="px-4 py-2">{{progress.amountOfIpv4Left}}</td>
<td class="px-4 py-2">{{data.amountOfIpv4Left}}</td>
</tr>
<tr>
<td class="px-4 py-2">Discarded db size</td>
<td class="px-4 py-2">{{progress.discardedDbSize}}</td>
<td class="px-4 py-2">{{data.discardedDbSize}}</td>
</tr>
<tr>
<td class="px-4 py-2">Filtered db size</td>
<td class="px-4 py-2">{{progress.filteredDbSize}}</td>
<td class="px-4 py-2">{{data.filteredDbSize}}</td>
</tr>
<tr>
<td class="px-4 py-2">Unfiltered db size</td>
<td class="px-4 py-2">{{progress.myDbSize}}</td>
<td class="px-4 py-2">{{data.myDbSize}}</td>
</tr>
</tbody>
</table>

View File

@ -1,20 +0,0 @@
export default function getProgress(){
const progress = ref(null as Progress | null);
fetch('https://proxy.rbwr.dk/progress', {
method: 'GET',
headers: {'Content-Type': 'application/json'}
})
.then(response => response.json())
.then((data: Progress) => {
if (data && data.percentageOfIpv4Scanned) {
progress.value = data;
} else {
console.error("Invalid data received from API");
console.error(data);
}
});
return progress;
}

View File

@ -1,4 +1,4 @@
interface Progress {
interface ProgressType {
percentageOfIpv4Scanned: number; // assuming this is a number
totalFiltered: bigint;
amountOfIpv4Left: bigint;
@ -6,4 +6,9 @@ interface Progress {
discardedDbSize: bigint;
filteredDbSize: bigint;
myDbSize: bigint;
}
}
type CacheEntry<T> = {
data: T;
timestamp: number;
};

View File

@ -0,0 +1,34 @@
export function fetchWithCache<Type>(
cacheKey: string,
fetchFunction: () => Promise<Type>,
maxAge: number = 5 // 30 seconds
): Promise<Type> {
return new Promise(async (resolve, reject) => {
try {
const cachedData = localStorage.getItem(cacheKey);
if (cachedData) {
const { data, timestamp } = JSON.parse(cachedData) as CacheEntry<Type>;
const now = Date.now();
const ageInSeconds = (now - timestamp) / 1000;
// Check if cache is still valid
if (ageInSeconds < maxAge) {
return resolve(data);
}
}
// Cache is missing or expired, fetch fresh data
const freshData = await fetchFunction();
const cacheEntry: CacheEntry<Type> = {
data: freshData,
timestamp: Date.now(),
};
localStorage.setItem(cacheKey, JSON.stringify(cacheEntry));
resolve(freshData);
} catch (error) {
reject(error);
}
});
}