mirror of
https://github.com/michivonah/themepark-assistant.git
synced 2025-12-22 22:16:29 +01:00
improve error handling in background jobs #3
This commit is contained in:
parent
6a60e3c10a
commit
04ae271e1e
8 changed files with 75 additions and 27 deletions
49
api/src/errors/background-error.ts
Normal file
49
api/src/errors/background-error.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Error classes for background jobs
|
||||
|
||||
// Class for custom background errors
|
||||
export class BackgroundJobError extends Error{
|
||||
cause?: unknown;
|
||||
|
||||
constructor(message: string, cause?: unknown){
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
this.cause = cause;
|
||||
}
|
||||
}
|
||||
|
||||
// Errors based on class BackgroundJobError
|
||||
export class BackgroundDatabaseError extends BackgroundJobError{
|
||||
constructor(cause?: unknown){
|
||||
super('Database request failed.', cause);
|
||||
}
|
||||
}
|
||||
|
||||
export class BackgroundFetchError extends BackgroundJobError{
|
||||
constructor(cause?: unknown){
|
||||
super('Fetching data failed', cause);
|
||||
}
|
||||
}
|
||||
|
||||
export class AttractionImportError extends BackgroundJobError{
|
||||
constructor(cause?: unknown){
|
||||
super('Failed to import attractions into database.', cause);
|
||||
}
|
||||
}
|
||||
|
||||
export class ThemeparkUpdateError extends BackgroundJobError{
|
||||
constructor(cause?: unknown){
|
||||
super('Failed to update themepark data.', cause);
|
||||
}
|
||||
}
|
||||
|
||||
export class KVParseError extends BackgroundJobError{
|
||||
constructor(key: string, cause?: unknown){
|
||||
super(`Failed to parse JSON from KV, affected key: ${key}`, cause);
|
||||
}
|
||||
}
|
||||
|
||||
export class SendNotificationError extends BackgroundJobError{
|
||||
constructor(cause?: unknown){
|
||||
super('Failed to send notification.', cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import { getDbEnv } from '../db/client'
|
|||
import { subscribedThemeparks, attractionSubscriptions } from "../db/schema";
|
||||
import { SubscribedThemeparks } from "../types/subscribed-themeparks";
|
||||
import { AttractionSubscription } from "../types/attraction-subscriptions";
|
||||
import { KVParseError, SendNotificationError } from "../errors/background-error";
|
||||
import httpRequest from "../lib/http-request";
|
||||
import fetchAttractions from "../lib/fetch-attractions";
|
||||
|
||||
|
|
@ -11,6 +12,7 @@ import fetchAttractions from "../lib/fetch-attractions";
|
|||
* waittime in cache & send notification about changes in waittime.
|
||||
* @param env Connection to Cloudflare
|
||||
*/
|
||||
// TODO: split into batches by cron, when more than 10 parks have to be fetched -> like update-attraction-list.ts
|
||||
export default async function updateWaittimes(env: Env): Promise<void>{
|
||||
const db = getDbEnv(env);
|
||||
const subscribedParks = await db.select().from(subscribedThemeparks);
|
||||
|
|
@ -54,7 +56,7 @@ async function getJsonFromKV<T>(env: Env, key: string, defaultValue: T): Promise
|
|||
return JSON.parse(cache) as T;
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Failed to parse JSON from KV, affected key: ${key}, error: ${e}`);
|
||||
throw new KVParseError(key, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +133,7 @@ async function sendNotification(webhookUrl: string, message: string, type: strin
|
|||
});
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Failed to send notification: ${e}`);
|
||||
throw new SendNotificationError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { attraction, themepark } from '../db/schema'
|
|||
import { inArray } from 'drizzle-orm'
|
||||
import { Attraction } from '../types/attraction'
|
||||
import { ThemeparkSelect } from '../types/themepark'
|
||||
import { AttractionImportError, BackgroundDatabaseError } from '../errors/background-error'
|
||||
import asyncBatchJob from '../lib/async-batch-job'
|
||||
import fetchAttractions from '../lib/fetch-attractions'
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ async function getThemeparks(env: Env): Promise<ThemeparkAPI[]>{
|
|||
return themeparks;
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Failed to get themeparks from database: ${e}`);
|
||||
throw new BackgroundDatabaseError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +51,7 @@ async function getAttractionsByParks(env: Env, parks: ThemeparkAPI[]): Promise<A
|
|||
return attractions;
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Failed to get attractions from database: ${e}`);
|
||||
throw new BackgroundDatabaseError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +87,7 @@ async function importAttractionsByParks(env: Env, parks: ThemeparkAPI[]): Promis
|
|||
}
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Failed to import attractions into database: ${e}`);
|
||||
throw new AttractionImportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +100,6 @@ async function importAttractionsByParks(env: Env, parks: ThemeparkAPI[]): Promis
|
|||
* @param cron The cron statement specified to run the background jobs; used for batch size calculation
|
||||
*/
|
||||
export async function batchAttractionImport(env: Env, timestamp: number, cron: string): Promise<void>{
|
||||
try{
|
||||
const themeparks = await getThemeparks(env); // all themeparks
|
||||
const executionHour = new Date(timestamp).getUTCHours(); // current hour, in which job is executed
|
||||
const executionTimes = getExecutionCountFromCron(cron, 1); // how often the job is executed
|
||||
|
|
@ -117,10 +117,6 @@ export async function batchAttractionImport(env: Env, timestamp: number, cron: s
|
|||
// import attractions from current time batch
|
||||
await importAttractionsByParks(env, batch);
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Failed to split attraction import by time: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates how often cron job gets executed
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { getDbEnv } from '../db/client'
|
||||
import { themepark } from '../db/schema'
|
||||
import { countryCodesDE } from '../lib/countries'
|
||||
import { BackgroundFetchError, ThemeparkUpdateError } from '../errors/background-error'
|
||||
import httpRequest from '../lib/http-request'
|
||||
import asyncBatchJob from '../lib/async-batch-job'
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ async function fetchThemeparks(
|
|||
return result;
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Fetching themeparks failed: ${e}`);
|
||||
throw new BackgroundFetchError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,6 +68,6 @@ export async function updateThemeparkData(env: Env): Promise<void>{
|
|||
}
|
||||
}
|
||||
catch(e){
|
||||
console.error(`Failed to update themepark data: ${e}`);
|
||||
throw new ThemeparkUpdateError(e);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import { UserSelect } from "../types/user";
|
|||
import { user } from "../db/schema";
|
||||
import { like } from "drizzle-orm";
|
||||
import { DrizzleD1Database } from "drizzle-orm/d1";
|
||||
import { MissingMailError, UserInactiveError, DatabaseError } from "../types/error";
|
||||
import { MissingMailError, UserInactiveError, DatabaseError } from "../errors/http-error";
|
||||
|
||||
/**
|
||||
* Returns the details of a user from the given context
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Hono, Context } from 'hono'
|
|||
import { getDbContext } from '../db/client'
|
||||
import { attractionNotification, notificationMethod } from '../db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { DatabaseError, InvalidParameter, MissingParameter } from '../types/error'
|
||||
import { DatabaseError, InvalidParameter, MissingParameter } from '../errors/http-error'
|
||||
import { getUser } from '../lib/user-auth'
|
||||
import { Message } from '../types/response'
|
||||
import { NotificationMethodSelect } from '../types/notification-method'
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { getDbContext } from '../db/client'
|
|||
import { themepark, attraction } from '../db/schema'
|
||||
import { responseCache } from '../lib/cache'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { DatabaseError } from '../types/error'
|
||||
import { DatabaseError } from '../errors/http-error'
|
||||
|
||||
const app = new Hono()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue