mirror of
https://github.com/michivonah/themepark-assistant.git
synced 2025-12-22 22:16:29 +01:00
refactoring background job for updating themepark data
This commit is contained in:
parent
f3375cfa20
commit
ff859475a0
2 changed files with 56 additions and 22 deletions
|
|
@ -2,6 +2,7 @@ import { getDbEnv } from '../db/client'
|
||||||
import { themepark } from '../db/schema'
|
import { themepark } from '../db/schema'
|
||||||
import { countryCodesDE } from '../lib/countries'
|
import { countryCodesDE } from '../lib/countries'
|
||||||
import fetchData from '../lib/fetch-data'
|
import fetchData from '../lib/fetch-data'
|
||||||
|
import asyncBatchJob from '../lib/async-batch-job'
|
||||||
|
|
||||||
interface Park {
|
interface Park {
|
||||||
id: string,
|
id: string,
|
||||||
|
|
@ -9,42 +10,58 @@ interface Park {
|
||||||
land: string
|
land: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateThemeparkData(env: Env): Promise<void>{
|
/**
|
||||||
|
* Fetches a list of available themeparks from an external API
|
||||||
|
* @param endpoint Endpoint where to fetch data from (default: https://api.wartezeiten.app/v1/parks)
|
||||||
|
* @param lang Language specified in the request's header (default: de)
|
||||||
|
* @returns Object with all themeparks
|
||||||
|
*/
|
||||||
|
async function fetchThemeparks(
|
||||||
|
endpoint: string = "https://api.wartezeiten.app/v1/parks",
|
||||||
|
lang: string = "de"
|
||||||
|
): Promise<Park[]>{
|
||||||
try{
|
try{
|
||||||
// fetch all available themeparks from external API
|
|
||||||
const endpoint = "https://api.wartezeiten.app/v1/parks"
|
|
||||||
const headers = {
|
const headers = {
|
||||||
'language':'de'
|
'language':lang
|
||||||
}
|
}
|
||||||
const availableThemeparks = await fetchData<Park[]>(endpoint, headers);
|
const result = await fetchData<Park[]>(endpoint, headers);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
throw new Error(`Fetching themeparks failed: ${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// internal db queries
|
/**
|
||||||
|
* Loads themeparks from API and compare to current themeparks in DB.
|
||||||
|
* Adds the missing themeparks to the DB in multiple batches
|
||||||
|
* @param env DB Connection
|
||||||
|
*/
|
||||||
|
export async function updateThemeparkData(env: Env): Promise<void>{
|
||||||
|
const availableThemeparks = await fetchThemeparks();
|
||||||
|
|
||||||
|
try{
|
||||||
|
// get current list of themeparks from DB
|
||||||
const db = getDbEnv(env);
|
const db = getDbEnv(env);
|
||||||
const currentThemeparks = await db.select({
|
const currentThemeparks = await db.select({
|
||||||
apiName: themepark.apiName
|
apiName: themepark.apiName
|
||||||
}).from(themepark);
|
}).from(themepark);
|
||||||
|
|
||||||
let newParks = [];
|
// filter to get only the new parks
|
||||||
|
const newParks = availableThemeparks.filter(
|
||||||
for (let park of availableThemeparks){
|
park => currentThemeparks.length == 0 || !currentThemeparks.some(id => id.apiName == park.id)
|
||||||
if(currentThemeparks.length == 0 || !currentThemeparks.some(id => id.apiName == park.id)){ // checks if id already exists in db
|
).map(park => ({
|
||||||
newParks.push({
|
name: park.name,
|
||||||
name: park.name,
|
apiName: park.id,
|
||||||
apiName: park.id,
|
countrycode: countryCodesDE[park.land]
|
||||||
countrycode: countryCodesDE[park.land]
|
}));
|
||||||
});
|
|
||||||
console.log(`${park.id} is missing in DB`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only run queries, when new parks were found
|
// only run queries, when new parks were found
|
||||||
if (newParks.length != 0){
|
if (newParks.length != 0){
|
||||||
// split into multiple batches, to apply with D1's limits
|
// split into multiple batches, to apply with D1's limits
|
||||||
const batchSize = 20;
|
await asyncBatchJob(newParks, 20, async (batch) => {
|
||||||
for (let i = 0; i < newParks.length; i += batchSize){
|
|
||||||
const batch = newParks.slice(i, i + batchSize);
|
|
||||||
await db.insert(themepark).values(batch);
|
await db.insert(themepark).values(batch);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(e){
|
catch(e){
|
||||||
|
|
|
||||||
17
api/src/lib/async-batch-job.ts
Normal file
17
api/src/lib/async-batch-job.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Run any async operation in (multiple) batches
|
||||||
|
* @param data Array to split into batches
|
||||||
|
* @param batchSize Amount of items per batch (default: 20)
|
||||||
|
* @param callback Async function to execute for each batch
|
||||||
|
*/
|
||||||
|
export default async function asyncBatchJob<T>(data: T[], batchSize: number = 20, callback: (batch: T[], batchIndex: number) => Promise<void>): Promise<void>{
|
||||||
|
try{
|
||||||
|
for (let i = 0; i < data.length; i += batchSize){
|
||||||
|
const batch = data.slice(i, i + batchSize);
|
||||||
|
await callback(batch, i / batchSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
throw new Error(`Batch execution failed: ${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue