fix: fetchFromMultipleSources returns errorOccurred only if all sources fail
This commit is contained in:
@@ -49,7 +49,7 @@ const app = new OpenAPIHono<Env>();
|
|||||||
app.openapi(route, async (c) => {
|
app.openapi(route, async (c) => {
|
||||||
const aniListId = Number(c.req.param("aniListId"));
|
const aniListId = Number(c.req.param("aniListId"));
|
||||||
|
|
||||||
const { result: episodes, errors } = await fetchFromMultipleSources([
|
const { result: episodes, errorOccurred } = await fetchFromMultipleSources([
|
||||||
() => {
|
() => {
|
||||||
const isAnifyEnabled = readEnvVariable<boolean>(c.env, "ENABLE_ANIFY");
|
const isAnifyEnabled = readEnvVariable<boolean>(c.env, "ENABLE_ANIFY");
|
||||||
return getEpisodesFromAnify(isAnifyEnabled, aniListId);
|
return getEpisodesFromAnify(isAnifyEnabled, aniListId);
|
||||||
@@ -64,7 +64,7 @@ app.openapi(route, async (c) => {
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (errors?.length > 0) {
|
if (errorOccurred) {
|
||||||
return c.json(ErrorResponse, { status: 500 });
|
return c.json(ErrorResponse, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ app.openapi(route, async (c) => {
|
|||||||
const page = Number(c.req.query("page") ?? 1);
|
const page = Number(c.req.query("page") ?? 1);
|
||||||
const limit = Number(c.req.query("limit") ?? 10);
|
const limit = Number(c.req.query("limit") ?? 10);
|
||||||
|
|
||||||
const { result: response, errors } = await fetchFromMultipleSources([
|
const { result: response, errorOccurred } = await fetchFromMultipleSources([
|
||||||
() => fetchSearchResultsFromAnilist(query, page, limit),
|
() => fetchSearchResultsFromAnilist(query, page, limit),
|
||||||
() => fetchSearchResultsFromAmvstrm(query, page, limit),
|
() => fetchSearchResultsFromAmvstrm(query, page, limit),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
return c.json({
|
return c.json({
|
||||||
success: (errors ?? []).length === 0,
|
success: !errorOccurred,
|
||||||
results: [],
|
results: [],
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -48,12 +48,12 @@ app.openapi(route, async (c) => {
|
|||||||
const aniListId = Number(c.req.query("id"));
|
const aniListId = Number(c.req.query("id"));
|
||||||
const aniListToken = c.req.header("X-AniList-Token");
|
const aniListToken = c.req.header("X-AniList-Token");
|
||||||
|
|
||||||
const { result: title, errors } = await fetchFromMultipleSources([
|
const { result: title, errorOccurred } = await fetchFromMultipleSources([
|
||||||
() => fetchTitleFromAnilist(aniListId, aniListToken ?? undefined),
|
() => fetchTitleFromAnilist(aniListId, aniListToken ?? undefined),
|
||||||
() => fetchTitleFromAmvstrm(aniListId),
|
() => fetchTitleFromAmvstrm(aniListId),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (errors?.length > 0) {
|
if (errorOccurred) {
|
||||||
return c.json(ErrorResponse, { status: 500 });
|
return c.json(ErrorResponse, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ describe("fetchFromMultipleSources", () => {
|
|||||||
expect(result).toEqual(2);
|
expect(result).toEqual(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has promises with valid responses, contains no errors", async () => {
|
it("has promises with valid responses, no error occurred", async () => {
|
||||||
const { errors } = await fetchFromMultipleSources<number>([
|
const { errorOccurred } = await fetchFromMultipleSources<number>([
|
||||||
() => Promise.resolve(undefined),
|
() => Promise.resolve(undefined),
|
||||||
() => Promise.resolve(null),
|
() => Promise.resolve(null),
|
||||||
() => Promise.reject(),
|
() => Promise.reject(),
|
||||||
@@ -30,28 +30,25 @@ describe("fetchFromMultipleSources", () => {
|
|||||||
() => Promise.resolve(3),
|
() => Promise.resolve(3),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(errors).toBeNull();
|
expect(errorOccurred).toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has promises with no valid responses, returns null", async () => {
|
it("has promises that all throw, returns null", async () => {
|
||||||
const { result } = await fetchFromMultipleSources<number>([
|
const { result } = await fetchFromMultipleSources<number>([
|
||||||
() => Promise.resolve(null),
|
|
||||||
() => Promise.reject("error"),
|
() => Promise.reject("error"),
|
||||||
() => Promise.resolve(undefined),
|
() => Promise.reject(new Error("error")),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(result).toBeNull();
|
expect(result).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has promises with no valid responses, contains error", async () => {
|
it("has promises that all throw, contains error", async () => {
|
||||||
const { errors } = await fetchFromMultipleSources<number>([
|
const { errorOccurred } = await fetchFromMultipleSources<number>([
|
||||||
() => Promise.resolve(null),
|
|
||||||
() => Promise.reject("error"),
|
() => Promise.reject("error"),
|
||||||
() => Promise.reject(new Error("error")),
|
() => Promise.reject(new Error("error")),
|
||||||
() => Promise.resolve(undefined),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(errors).toEqual(["error", new Error("error")]);
|
expect(errorOccurred).toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has promises but cache has value, returns cached value", async () => {
|
it("has promises but cache has value, returns cached value", async () => {
|
||||||
@@ -71,7 +68,7 @@ describe("fetchFromMultipleSources", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("has promises but cache has value, contains no errors", async () => {
|
it("has promises but cache has value, contains no errors", async () => {
|
||||||
const { errors } = await fetchFromMultipleSources<number>(
|
const { errorOccurred } = await fetchFromMultipleSources<number>(
|
||||||
[
|
[
|
||||||
() => Promise.resolve(null),
|
() => Promise.resolve(null),
|
||||||
() => Promise.reject("error"),
|
() => Promise.reject("error"),
|
||||||
@@ -83,7 +80,7 @@ describe("fetchFromMultipleSources", () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(errors).toBeNull();
|
expect(errorOccurred).toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has promises, no cached value, no valid response, should not save in cache", async () => {
|
it("has promises, no cached value, no valid response, should not save in cache", async () => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ type OptionalArgs<T> =
|
|||||||
|
|
||||||
interface FetchFromMultipleSourcesResult<T> {
|
interface FetchFromMultipleSourcesResult<T> {
|
||||||
result: T | null;
|
result: T | null;
|
||||||
errors: (Error | string | undefined)[] | null;
|
errorOccurred: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchFromMultipleSources<T>(
|
export async function fetchFromMultipleSources<T>(
|
||||||
@@ -19,21 +19,21 @@ export async function fetchFromMultipleSources<T>(
|
|||||||
): Promise<FetchFromMultipleSourcesResult<T>> {
|
): Promise<FetchFromMultipleSourcesResult<T>> {
|
||||||
let result = await args?.fetchFromCache?.();
|
let result = await args?.fetchFromCache?.();
|
||||||
if (result) {
|
if (result) {
|
||||||
return { result, errors: null };
|
return { result, errorOccurred: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fetchPromises.length === 0) {
|
if (fetchPromises.length === 0) {
|
||||||
throw new Error("fetchPromises cannot be empty");
|
throw new Error("fetchPromises cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
let errors: Record<number, Error> = {};
|
let errorCount = 0;
|
||||||
for (let i = 0; i < fetchPromises.length; i++) {
|
for (let i = 0; i < fetchPromises.length; i++) {
|
||||||
const promise = fetchPromises[i];
|
const promise = fetchPromises[i];
|
||||||
try {
|
try {
|
||||||
result = await promise();
|
result = await promise();
|
||||||
if (result) break;
|
if (result) break;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors[i] = e as Error;
|
errorCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,6 @@ export async function fetchFromMultipleSources<T>(
|
|||||||
result = result ?? null;
|
result = result ?? null;
|
||||||
return {
|
return {
|
||||||
result,
|
result,
|
||||||
errors:
|
errorOccurred: errorCount === fetchPromises.length,
|
||||||
!result && Object.keys(errors).length > 0 ? Object.values(errors) : null,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user