make loading beatsaver map hashes way faster
All checks were successful
deploy / deploy (push) Successful in 2m9s
All checks were successful
deploy / deploy (push) Successful in 2m9s
This commit is contained in:
parent
14f67af125
commit
b3c3be4b7c
@ -5,35 +5,61 @@ import { BeatsaverAPI } from "@/utils/beatsaver/api";
|
|||||||
export async function GET(request: Request) {
|
export async function GET(request: Request) {
|
||||||
const { searchParams } = new URL(request.url);
|
const { searchParams } = new URL(request.url);
|
||||||
const mapHashes = searchParams.get("hashes")?.split(",") ?? undefined;
|
const mapHashes = searchParams.get("hashes")?.split(",") ?? undefined;
|
||||||
|
|
||||||
if (!mapHashes) {
|
if (!mapHashes) {
|
||||||
return new Response("mapHashes parameter is required", { status: 400 });
|
return new Response("mapHashes parameter is required", { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const idOnly = searchParams.get("idonly") === "true";
|
const idOnly = searchParams.get("idonly") === "true";
|
||||||
let totalInCache = 0;
|
let totalInCache = 0;
|
||||||
|
|
||||||
const maps: Record<string, BeatsaverMap | { id: string }> = {};
|
const maps: Record<string, BeatsaverMap | { id: string }> = {};
|
||||||
for (const mapHash of mapHashes) {
|
|
||||||
|
const fetchMapFromCache = async (mapHash: string) => {
|
||||||
const cachedMap = await (
|
const cachedMap = await (
|
||||||
await Redis.client
|
await Redis.client
|
||||||
).get(`beatsaver:map:${mapHash}`);
|
).get(`beatsaver:map:${mapHash}`);
|
||||||
if (cachedMap) {
|
return cachedMap;
|
||||||
maps[mapHash] = JSON.parse(cachedMap);
|
};
|
||||||
totalInCache++;
|
|
||||||
} else {
|
const fetchAndCacheMap = async (mapHash: string) => {
|
||||||
const map = await BeatsaverAPI.fetchMapByHash(mapHash);
|
const beatSaverMap = await BeatsaverAPI.fetchMapByHash(mapHash);
|
||||||
if (!map) {
|
if (beatSaverMap) {
|
||||||
continue;
|
maps[mapHash] = idOnly ? { id: beatSaverMap.id } : beatSaverMap;
|
||||||
}
|
|
||||||
maps[mapHash] = map;
|
|
||||||
await (
|
await (
|
||||||
await Redis.client
|
await Redis.client
|
||||||
).set("beatsaver:map:" + mapHash, JSON.stringify(map), {
|
).set(
|
||||||
EX: 60 * 60 * 24 * 7, // 7 days
|
`beatsaver:map:${mapHash}`,
|
||||||
});
|
JSON.stringify(idOnly ? { id: beatSaverMap.id } : beatSaverMap),
|
||||||
|
"EX",
|
||||||
|
60 * 60 * 24 * 7,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (idOnly) {
|
for (const mapHash of mapHashes) {
|
||||||
maps[mapHash] = { id: (maps[mapHash] as BeatsaverMap).id };
|
const map = await fetchMapFromCache(mapHash);
|
||||||
|
if (map) {
|
||||||
|
maps[mapHash] = JSON.parse(map);
|
||||||
|
totalInCache++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalInCache === 0) {
|
||||||
|
const beatSaverMaps = await BeatsaverAPI.fetchMapsByHash(...mapHashes);
|
||||||
|
if (beatSaverMaps) {
|
||||||
|
for (const mapHash of mapHashes) {
|
||||||
|
const beatSaverMap = beatSaverMaps[mapHash.toLowerCase()];
|
||||||
|
if (beatSaverMap) {
|
||||||
|
await fetchAndCacheMap(mapHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const mapHash of mapHashes) {
|
||||||
|
if (!maps[mapHash]) {
|
||||||
|
await fetchAndCacheMap(mapHash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,15 +10,40 @@ export const BeatsaverFetchQueue = new FetchQueue();
|
|||||||
const BS_API_URL = ssrSettings.proxy + "/https://api.beatsaver.com";
|
const BS_API_URL = ssrSettings.proxy + "/https://api.beatsaver.com";
|
||||||
export const BS_GET_MAP_BY_HASH_URL = BS_API_URL + "/maps/hash/{}";
|
export const BS_GET_MAP_BY_HASH_URL = BS_API_URL + "/maps/hash/{}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the map info for the provided hashes
|
||||||
|
*
|
||||||
|
* @param hash the hashes for the maps
|
||||||
|
* @returns the map info
|
||||||
|
*/
|
||||||
|
async function fetchMapsByHash(
|
||||||
|
...hash: string[]
|
||||||
|
): Promise<{ [key: string]: BeatsaverMap } | undefined> {
|
||||||
|
const hashes = hash.join(",");
|
||||||
|
const response = await BeatsaverFetchQueue.fetch(
|
||||||
|
formatString(
|
||||||
|
BS_GET_MAP_BY_HASH_URL,
|
||||||
|
true,
|
||||||
|
hashes.substring(0, hashes.length - 1),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const json = await response.json();
|
||||||
|
|
||||||
|
// Check if there was an error fetching the user data
|
||||||
|
if (json.error) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the map info for the provided hash
|
* Returns the map info for the provided hash
|
||||||
*
|
*
|
||||||
* @param hash the hash of the map
|
* @param hash the hash of the map
|
||||||
* @returns the map info
|
* @returns the map info
|
||||||
*/
|
*/
|
||||||
async function fetchMapByHash(
|
async function fetchMapByHash(hash: string): Promise<BeatsaverMap | undefined> {
|
||||||
hash: string,
|
|
||||||
): Promise<BeatsaverMap | undefined | null> {
|
|
||||||
const response = await BeatsaverFetchQueue.fetch(
|
const response = await BeatsaverFetchQueue.fetch(
|
||||||
formatString(BS_GET_MAP_BY_HASH_URL, true, hash),
|
formatString(BS_GET_MAP_BY_HASH_URL, true, hash),
|
||||||
);
|
);
|
||||||
@ -29,9 +54,10 @@ async function fetchMapByHash(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return json as BeatsaverMap;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BeatsaverAPI = {
|
export const BeatsaverAPI = {
|
||||||
|
fetchMapsByHash,
|
||||||
fetchMapByHash,
|
fetchMapByHash,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user