implement background job for updating themepark data

This commit is contained in:
Michi 2025-09-13 18:19:36 +02:00
parent cd5ae0f69f
commit d60650a3a5
4 changed files with 108 additions and 0 deletions

View file

@ -10,6 +10,9 @@ export default async function cronRouter(
case '* * * * *': case '* * * * *':
console.log('every minute'); console.log('every minute');
break; break;
case '0 4 7,14,21,28 * *':
await updateThemeparkData(env);
break;
default: default:
console.log('its me - the cron router'); console.log('its me - the cron router');
break; break;

View file

@ -0,0 +1,53 @@
import { getDbEnv } from '../db/client'
import { themepark } from '../db/schema'
import { countryCodesDE } from '../lib/countries'
import fetchData from '../lib/fetch-data'
interface Park {
id: string,
name: string,
land: string
}
export async function updateThemeparkData(env: Env): Promise<void>{
try{
// fetch all available themeparks from external API
const endpoint = "https://api.wartezeiten.app/v1/parks"
const headers = {
'language':'de'
}
const availableThemeparks = await fetchData<Park[]>(endpoint, headers);
// internal db queries
const db = getDbEnv(env);
const currentThemeparks = await db.select({
apiName: themepark.apiName
}).from(themepark);
let newParks = [];
for (let park of availableThemeparks){
if(currentThemeparks.length == 0 || !currentThemeparks.some(id => id.apiName == park.id)){ // checks if id already exists in db
newParks.push({
name: park.name,
apiName: park.id,
countrycode: countryCodesDE[park.land]
});
console.log(`${park.id} is missing in DB`)
}
}
// only run queries, when new parks were found
if (newParks.length != 0){
// split into multiple batches, to apply with D1's limits
const batchSize = 20;
for (let i = 0; i < newParks.length; i += batchSize){
const batch = newParks.slice(i, i + batchSize);
await db.insert(themepark).values(batch);
}
}
}
catch(e){
console.error(`Failed to update themepark data: ${e}`);
}
}

37
api/src/lib/countries.ts Normal file
View file

@ -0,0 +1,37 @@
// key value pair countryname (german) to countrycode
// incomplete list with just the countries from the external api (api.wartezeiten.app)
export const countryCodesDE: Record<string, string> = {
"Belgien":"BE",
"Deutschland":"DE",
"Dänemark":"DK",
"Frankreich":"FR",
"Großbritannien":"GB",
"Italien":"IT",
"Niederlande":"NL",
"Polen":"PL",
"Schweden":"SE",
"Schweiz":"CH",
"Spanien":"ES",
"Vereinigte Staaten":"US",
"Vereinigtes Königreich":"UK",
"Österreich":"AT"
};
export const countryCodesEN: Record<string, string> = {
"Austria":"AT",
"Belgium":"BE",
"Denmark":"DK",
"France":"FR",
"Germany":"DE",
"Great Britain":"GB",
"Italy":"IT",
"Netherlands":"NL",
"Poland":"PL",
"Spain":"ES",
"Sweden":"SE",
"Switzerland":"CH",
"United Kingdom":"UK",
"United States":"US"
};
// source: https://de.wikipedia.org/wiki/ISO-3166-1-Kodierliste

15
api/src/lib/fetch-data.ts Normal file
View file

@ -0,0 +1,15 @@
// typesafe api fetch function
export default async function fetchData<T>(endpoint: string, headers: Record<string, string> = {}, method: string = 'GET'): Promise<T>{
async function gatherResponse(response: Response): Promise<T>{
return await response.json();
}
const response: Response = await fetch(endpoint, { method: method, headers: headers});
if (!response.ok){
throw new Error(`HTTP error! Status: ${response.status}`);
}
const result: T = await gatherResponse(response);
return result;
}