fix: Prevent MongoDB client promise being cached (#66977)

### 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](c08bc96353)
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).
This commit is contained in:
Aldo Schumann 2024-06-18 17:47:07 +10:00 committed by GitHub
parent dc461512d3
commit 86dbcbea43
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 9 additions and 26 deletions

View file

@ -13,27 +13,24 @@ const options = {
},
};
let client;
let clientPromise: Promise<MongoClient>;
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?: 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;

View file

@ -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 },
};

View file

@ -1,5 +0,0 @@
import { MongoClient } from "mongodb";
declare global {
var _mongoClientPromise: Promise<MongoClient>;
}