Source: lib/db/mongodb.js

  1. // This approach is taken from https://github.com/vercel/next.js/tree/canary/examples/with-mongodb
  2. import { MongoClient } from "mongodb";
  3. import { backOff } from "exponential-backoff";
  4. if (!process.env.MONGODB_DB) {
  5. throw new Error("Please add your Mongo DB Name to .env");
  6. }
  7. if (!process.env.MONGODB_URI) {
  8. throw new Error("Please add your Mongo URI to .env");
  9. }
  10. const uri = process.env.MONGODB_URI;
  11. const options = {
  12. useUnifiedTopology: true,
  13. useNewUrlParser: true,
  14. dbName: process.env.MONGODB_DB,
  15. };
  16. let client;
  17. let clientPromise;
  18. if (process.env.NODE_ENV === "development") {
  19. // In development mode, use a global variable so that the value
  20. // is preserved across module reloads caused by HMR (Hot Module Replacement).
  21. if (!global._mongoClientPromise) {
  22. client = new MongoClient(uri, options);
  23. global._mongoClientPromise = client.connect();
  24. }
  25. clientPromise = global._mongoClientPromise;
  26. } else {
  27. // In production mode, it's best to not use a global variable.
  28. client = new MongoClient(uri, options);
  29. clientPromise = client.connect();
  30. }
  31. async function _connectToDatabase() {
  32. const client = await getMongoClient();
  33. await client.connect();
  34. const db = client.db(process.env.MONGODB_DB);
  35. return db;
  36. }
  37. /**
  38. * Connects to the database and returns the database object.
  39. * Uses exponential backoff to retry the connection if it fails.
  40. */
  41. export async function connectToDatabase() {
  42. return await backOff(() => _connectToDatabase(), {
  43. numOfAttempts: 10,
  44. jitter: "full",
  45. retry: (error, attemptNumber) => {
  46. console.warn(`Retrying connection to database #${attemptNumber}`, error);
  47. return true;
  48. },
  49. });
  50. }
  51. /**
  52. * Gets and resolves the MongoDB client promise.
  53. */
  54. export async function getMongoClient() {
  55. const client = await clientPromise;
  56. if (!client) {
  57. throw new Error("Not connected to database");
  58. }
  59. return client;
  60. }
  61. /**
  62. * Connects to the database and gets the posts collection.
  63. */
  64. export async function getPostsCollection() {
  65. return (await connectToDatabase()).collection("dreams");
  66. }
  67. /**
  68. * Connects to the database and gets the comments collection.
  69. */
  70. export async function getCommentsCollection() {
  71. return (await connectToDatabase()).collection("comments");
  72. }
  73. /**
  74. * Connects to the database and gets the stars collection.
  75. */
  76. export async function getStarsCollection() {
  77. return (await connectToDatabase()).collection("stars");
  78. }
  79. /**
  80. * Connects to the database and gets the inbox collection.
  81. */
  82. export async function getInboxCollection() {
  83. return (await connectToDatabase()).collection("inbox");
  84. }
  85. /**
  86. * Connects to the database and gets the completions collection.
  87. */
  88. export async function getCompletionsCollection() {
  89. return (await connectToDatabase()).collection("completions");
  90. }
  91. /**
  92. * Connects to the database and gets the cosine_similarity collection.
  93. * This collections is never read from (on this codebase), only written to.
  94. * It is used to store the results of the cosine similarity score between
  95. * post texts, which help evolve the platform.
  96. */
  97. export async function getCosineSimilarityCollection() {
  98. return (await connectToDatabase()).collection("cosine_similarity");
  99. }
  100. /**
  101. *
  102. * Connects to the database and gets the users collection.
  103. * This collection is automatically generated by next-auth
  104. */
  105. export async function getUsersCollection() {
  106. return (await connectToDatabase()).collection("users");
  107. }
  108. /**
  109. * Connects to the database and gets the users collection.
  110. * This collection is automatically generated by next-auth
  111. */
  112. export async function getAccountsCollection() {
  113. return (await connectToDatabase()).collection("accounts");
  114. }
  115. // Export a module-scoped MongoClient promise. By doing this in a
  116. // separate module, the client can be shared across functions.
  117. export default clientPromise;
  118. export { clientPromise as clientPromise };