// This approach is taken from https://github.com/vercel/next.js/tree/canary/examples/with-mongodb
import { MongoClient } from "mongodb";
import { backOff } from "exponential-backoff";
if (!process.env.MONGODB_DB) {
throw new Error("Please add your Mongo DB Name to .env");
}
if (!process.env.MONGODB_URI) {
throw new Error("Please add your Mongo URI to .env");
}
const uri = process.env.MONGODB_URI;
const options = {
useUnifiedTopology: true,
useNewUrlParser: true,
dbName: process.env.MONGODB_DB,
};
let client;
let clientPromise;
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).
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options);
global._mongoClientPromise = client.connect();
}
clientPromise = global._mongoClientPromise;
} else {
// In production mode, it's best to not use a global variable.
client = new MongoClient(uri, options);
clientPromise = client.connect();
}
async function _connectToDatabase() {
const client = await getMongoClient();
await client.connect();
const db = client.db(process.env.MONGODB_DB);
return db;
}
/**
* Connects to the database and returns the database object.
* Uses exponential backoff to retry the connection if it fails.
*/
export async function connectToDatabase() {
return await backOff(() => _connectToDatabase(), {
numOfAttempts: 10,
jitter: "full",
retry: (error, attemptNumber) => {
console.warn(`Retrying connection to database #${attemptNumber}`, error);
return true;
},
});
}
/**
* Gets and resolves the MongoDB client promise.
*/
export async function getMongoClient() {
const client = await clientPromise;
if (!client) {
throw new Error("Not connected to database");
}
return client;
}
/**
* Connects to the database and gets the posts collection.
*/
export async function getPostsCollection() {
return (await connectToDatabase()).collection("dreams");
}
/**
* Connects to the database and gets the comments collection.
*/
export async function getCommentsCollection() {
return (await connectToDatabase()).collection("comments");
}
/**
* Connects to the database and gets the stars collection.
*/
export async function getStarsCollection() {
return (await connectToDatabase()).collection("stars");
}
/**
* Connects to the database and gets the inbox collection.
*/
export async function getInboxCollection() {
return (await connectToDatabase()).collection("inbox");
}
/**
* Connects to the database and gets the completions collection.
*/
export async function getCompletionsCollection() {
return (await connectToDatabase()).collection("completions");
}
/**
* Connects to the database and gets the cosine_similarity collection.
* This collections is never read from (on this codebase), only written to.
* It is used to store the results of the cosine similarity score between
* post texts, which help evolve the platform.
*/
export async function getCosineSimilarityCollection() {
return (await connectToDatabase()).collection("cosine_similarity");
}
/**
*
* Connects to the database and gets the users collection.
* This collection is automatically generated by next-auth
*/
export async function getUsersCollection() {
return (await connectToDatabase()).collection("users");
}
/**
* Connects to the database and gets the users collection.
* This collection is automatically generated by next-auth
*/
export async function getAccountsCollection() {
return (await connectToDatabase()).collection("accounts");
}
// Export a module-scoped MongoClient promise. By doing this in a
// separate module, the client can be shared across functions.
export default clientPromise;
export { clientPromise as clientPromise };