Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/rides/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Ride } from "../types/ride"
import { Scheduler } from "./scheduler"
import { deleteRide } from "../data/redis"
import { logNames, logger } from "../logs"
import { RideNotInTimeError } from "../utils/errors"
import { RideNotInTimeError, rideFailureReason } from "../utils/errors"

const schedulers: Record<string, Scheduler> = {}

Expand All @@ -26,11 +26,16 @@ export const startRideNotifications = async (ride: Ride, isExisting: boolean = f
rideLogger.info(registerRideLog.success, { ...ride })
return { success: true, rideId: ride.rideId }
} catch (error) {
if (!(error instanceof RideNotInTimeError)) {
rideLogger.error(registerRideLog.failed, { error, ...ride })
const reason = rideFailureReason(error)

// Warn, not error: the ride is outside the startable window, which isn't a server fault — but still log it.
if (error instanceof RideNotInTimeError) {
rideLogger.warn(registerRideLog.failed, { reason, ...ride })
} else {
rideLogger.error(registerRideLog.failed, { error, reason, ...ride })
}

return { success: false }
return { success: false, reason }
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/rides/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class Scheduler {
await deleteRide(ride.rideId)
}

throw new RideNotInTimeError(logNames.scheduler.rideInPast)
throw new RideNotInTimeError(logNames.scheduler.rideInPast, "ride_in_past")
}

if (env === "production" && dayjs(route.departureTime).add(route.delay, "minutes").diff(dayjs(), "minutes") > 60) {
Expand All @@ -70,7 +70,7 @@ export class Scheduler {
await deleteRide(ride.rideId)
}

throw new RideNotInTimeError(logNames.scheduler.rideInFuture)
throw new RideNotInTimeError(logNames.scheduler.rideInFuture, "ride_in_future")
}

if (!isExisting) {
Expand Down
28 changes: 26 additions & 2 deletions src/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,26 @@
export class RideNotInTimeError extends Error {}
export class NotFoundRouteForRide extends Error {}
// Returned to the client alongside `success: false`, so it can tag its report with the cause.
export type RideFailureReason = "route_not_found" | "ride_in_past" | "ride_in_future" | "internal_error"

export class RideNotInTimeError extends Error {
constructor(
message: string,
readonly reason: Extract<RideFailureReason, "ride_in_past" | "ride_in_future">,
) {
super(message)
this.name = "RideNotInTimeError"
}
}

export class NotFoundRouteForRide extends Error {
readonly reason: RideFailureReason = "route_not_found"

constructor(message: string) {
super(message)
this.name = "NotFoundRouteForRide"
}
}

export const rideFailureReason = (error: unknown): RideFailureReason => {
if (error instanceof RideNotInTimeError || error instanceof NotFoundRouteForRide) return error.reason
return "internal_error"
}
Loading