diff --git a/.changeset/great-houses-study.md b/.changeset/great-houses-study.md new file mode 100644 index 000000000..4e6cd3548 --- /dev/null +++ b/.changeset/great-houses-study.md @@ -0,0 +1,5 @@ +--- +"@opennextjs/aws": patch +--- + +feat(cache): make dummy cache error ignorable diff --git a/packages/open-next/src/adapters/cache.ts b/packages/open-next/src/adapters/cache.ts index 9f87fa6e9..fcf6be034 100644 --- a/packages/open-next/src/adapters/cache.ts +++ b/packages/open-next/src/adapters/cache.ts @@ -1,3 +1,4 @@ +import { IgnorableError, isIgnorableError } from "utils/error"; import { isBinaryContentType } from "./binary"; import { debug, error, warn } from "./logger"; @@ -192,7 +193,11 @@ export default class S3Cache { } as CacheHandlerValue; } catch (e) { // We can usually ignore errors here as they are usually due to cache not being found - debug("Failed to get fetch cache", e); + if (isIgnorableError(e)) { + debug("Failed to get fetch cache", e.message); + } else { + debug("Failed to get fetch cache", e); + } return null; } } @@ -271,7 +276,11 @@ export default class S3Cache { return null; } catch (e) { // We can usually ignore errors here as they are usually due to cache not being found - debug("Failed to get body cache", e); + if (isIgnorableError(e)) { + debug("Failed to get body cache", e.message); + } else { + debug("Failed to get body cache", e); + } return null; } } @@ -409,7 +418,11 @@ export default class S3Cache { } debug("Finished setting cache"); } catch (e) { - error("Failed to set cache", e); + if (isIgnorableError(e)) { + debug("Failed to set cache", e.message); + } else { + error("Failed to set cache", e); + } } finally { // We need to resolve the promise even if there was an error detachedPromise?.resolve(); @@ -456,7 +469,11 @@ export default class S3Cache { await globalThis.tagCache.writeTags(toInsert); } } catch (e) { - error("Failed to revalidate tag", e); + if (isIgnorableError(e)) { + debug("Failed to revalidate tag", e.message); + } else { + error("Failed to revalidate tag", e); + } } } } diff --git a/packages/open-next/src/overrides/incrementalCache/dummy.ts b/packages/open-next/src/overrides/incrementalCache/dummy.ts index 7e84c96af..e6900dc78 100644 --- a/packages/open-next/src/overrides/incrementalCache/dummy.ts +++ b/packages/open-next/src/overrides/incrementalCache/dummy.ts @@ -1,15 +1,16 @@ import type { IncrementalCache } from "types/overrides"; +import { IgnorableError } from "utils/error"; const dummyIncrementalCache: IncrementalCache = { name: "dummy", get: async () => { - throw new Error("Dummy cache is not implemented"); + throw new IgnorableError('"Dummy" cache does not cache anything'); }, set: async () => { - throw new Error("Dummy cache is not implemented"); + throw new IgnorableError('"Dummy" cache does not cache anything'); }, delete: async () => { - throw new Error("Dummy cache is not implemented"); + throw new IgnorableError('"Dummy" cache does not cache anything'); }, }; diff --git a/packages/open-next/src/utils/error.ts b/packages/open-next/src/utils/error.ts index 2aae61c7b..f410aa2ea 100644 --- a/packages/open-next/src/utils/error.ts +++ b/packages/open-next/src/utils/error.ts @@ -5,6 +5,8 @@ export interface BaseOpenNextError { readonly logLevel: 0 | 1 | 2; } +const IGNORABLE_ERROR_NAME = "IgnorableError"; + // This is an error that can be totally ignored // It don't even need to be logged, or only in debug mode export class IgnorableError extends Error implements BaseOpenNextError { @@ -13,10 +15,17 @@ export class IgnorableError extends Error implements BaseOpenNextError { readonly logLevel = 0; constructor(message: string) { super(message); - this.name = "IgnorableError"; + this.name = IGNORABLE_ERROR_NAME; } } +// Note that `e instanceof IgnorableError` might not work across bundles +// embedding a distinct implementation of `IgnorableError`. +export function isIgnorableError(error: unknown): error is IgnorableError { + const anyError = error as any; + return anyError.__openNextInternal && anyError.name === IGNORABLE_ERROR_NAME; +} + // This is an error that can be recovered from // It should be logged but the process can continue export class RecoverableError extends Error implements BaseOpenNextError {