From 86dbcbea431f2fd85d94a72a9c2d35781154a5d7 Mon Sep 17 00:00:00 2001 From: Aldo Schumann Date: Tue, 18 Jun 2024 17:47:07 +1000 Subject: [PATCH] fix: Prevent MongoDB client promise being cached (#66977) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What? Update to [examples/with-mongodb](https://github.com/vercel/next.js/tree/canary/examples/with-mongodb) to incorporate fix from the MongoDB team. This should prevent intermittent serverless function timeouts due to cached promise. ### Why? Vercel users reported intermittent 500 errors when connecting to their MongoDB Atlas clusters in production environments. Full bug report: [NODE-6179](https://jira.mongodb.org/browse/NODE-6179) Related issues: - [10671](https://github.com/vercel/vercel/issues/10671) - [5708](https://github.com/orgs/vercel/discussions/5708) - [4297](https://github.com/orgs/vercel/discussions/4297) ### How? Solution by @baileympearson – thank you 🖤 [View commit](https://github.com/mongodb-developer/nextjs-with-mongodb/commit/c08bc96353f3d921766ece2ab2e9c4c647e398c7) in `mongodb-developer/nextjs-with-mongodb` --- - [x] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) - [x] Make sure the linting passes by running `pnpm build && pnpm lint`. [See linting docs](https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md). --- examples/with-mongodb/lib/mongodb.ts | 17 +++++++---------- examples/with-mongodb/pages/index.tsx | 13 ++----------- examples/with-mongodb/types/mongodb.d.ts | 5 ----- 3 files changed, 9 insertions(+), 26 deletions(-) delete mode 100644 examples/with-mongodb/types/mongodb.d.ts diff --git a/examples/with-mongodb/lib/mongodb.ts b/examples/with-mongodb/lib/mongodb.ts index faa13cfe4e..3b722a1286 100644 --- a/examples/with-mongodb/lib/mongodb.ts +++ b/examples/with-mongodb/lib/mongodb.ts @@ -13,27 +13,24 @@ const options = { }, }; -let client; -let clientPromise: Promise; +let client: MongoClient; if (process.env.NODE_ENV === "development") { // In development mode, use a global variable so that the value // is preserved across module reloads caused by HMR (Hot Module Replacement). let globalWithMongo = global as typeof globalThis & { - _mongoClientPromise?: Promise; + _mongoClient?: MongoClient; }; - if (!globalWithMongo._mongoClientPromise) { - client = new MongoClient(uri, options); - globalWithMongo._mongoClientPromise = client.connect(); + if (!globalWithMongo._mongoClient) { + globalWithMongo._mongoClient = new MongoClient(uri, options); } - clientPromise = globalWithMongo._mongoClientPromise; + client = globalWithMongo._mongoClient; } else { // In production mode, it's best to not use a global variable. client = new MongoClient(uri, options); - clientPromise = client.connect(); } -// Export a module-scoped MongoClient promise. By doing this in a +// Export a module-scoped MongoClient. By doing this in a // separate module, the client can be shared across functions. -export default clientPromise; +export default client; diff --git a/examples/with-mongodb/pages/index.tsx b/examples/with-mongodb/pages/index.tsx index fc97a3e782..d1730715e1 100644 --- a/examples/with-mongodb/pages/index.tsx +++ b/examples/with-mongodb/pages/index.tsx @@ -1,5 +1,5 @@ import Head from "next/head"; -import clientPromise from "../lib/mongodb"; +import client from "../lib/mongodb"; import type { InferGetServerSidePropsType, GetServerSideProps } from "next"; type ConnectionStatus = { @@ -10,16 +10,7 @@ export const getServerSideProps: GetServerSideProps< ConnectionStatus > = async () => { try { - await clientPromise; - // `await clientPromise` will use the default database passed in the MONGODB_URI - // However you can use another database (e.g. myDatabase) by replacing the `await clientPromise` with the following code: - // - // `const client = await clientPromise` - // `const db = client.db("myDatabase")` - // - // Then you can execute queries against your database like so: - // db.find({}) or any of the MongoDB Node Driver commands - + await client.connect(); // `await client.connect()` will use the default database passed in the MONGODB_URI return { props: { isConnected: true }, }; diff --git a/examples/with-mongodb/types/mongodb.d.ts b/examples/with-mongodb/types/mongodb.d.ts deleted file mode 100644 index 489dc0a695..0000000000 --- a/examples/with-mongodb/types/mongodb.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { MongoClient } from "mongodb"; - -declare global { - var _mongoClientPromise: Promise; -}