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 client: MongoClient;
|
||||||
let clientPromise: Promise<MongoClient>;
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
// In development mode, use a global variable so that the value
|
// In development mode, use a global variable so that the value
|
||||||
// is preserved across module reloads caused by HMR (Hot Module Replacement).
|
// is preserved across module reloads caused by HMR (Hot Module Replacement).
|
||||||
let globalWithMongo = global as typeof globalThis & {
|
let globalWithMongo = global as typeof globalThis & {
|
||||||
_mongoClientPromise?: Promise<MongoClient>;
|
_mongoClient?: MongoClient;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!globalWithMongo._mongoClientPromise) {
|
if (!globalWithMongo._mongoClient) {
|
||||||
client = new MongoClient(uri, options);
|
globalWithMongo._mongoClient = new MongoClient(uri, options);
|
||||||
globalWithMongo._mongoClientPromise = client.connect();
|
|
||||||
}
|
}
|
||||||
clientPromise = globalWithMongo._mongoClientPromise;
|
client = globalWithMongo._mongoClient;
|
||||||
} else {
|
} else {
|
||||||
// In production mode, it's best to not use a global variable.
|
// In production mode, it's best to not use a global variable.
|
||||||
client = new MongoClient(uri, options);
|
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.
|
// 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 Head from "next/head";
|
||||||
import clientPromise from "../lib/mongodb";
|
import client from "../lib/mongodb";
|
||||||
import type { InferGetServerSidePropsType, GetServerSideProps } from "next";
|
import type { InferGetServerSidePropsType, GetServerSideProps } from "next";
|
||||||
|
|
||||||
type ConnectionStatus = {
|
type ConnectionStatus = {
|
||||||
|
@ -10,16 +10,7 @@ export const getServerSideProps: GetServerSideProps<
|
||||||
ConnectionStatus
|
ConnectionStatus
|
||||||
> = async () => {
|
> = async () => {
|
||||||
try {
|
try {
|
||||||
await clientPromise;
|
await client.connect(); // `await client.connect()` will use the default database passed in the MONGODB_URI
|
||||||
// `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
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { isConnected: true },
|
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