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:
parent
dc461512d3
commit
86dbcbea43
3 changed files with 9 additions and 26 deletions
|
@ -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;
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
|
5
examples/with-mongodb/types/mongodb.d.ts
vendored
5
examples/with-mongodb/types/mongodb.d.ts
vendored
|
@ -1,5 +0,0 @@
|
|||
import { MongoClient } from "mongodb";
|
||||
|
||||
declare global {
|
||||
var _mongoClientPromise: Promise<MongoClient>;
|
||||
}
|
Loading…
Reference in a new issue