操作 `.findOne()` 缓冲在 10000 毫秒后超时 - Next.js Mongoose

问题描述 投票:0回答:1

在我的 NextJS 项目中,我正在开发一个新闻通讯应用程序。我的数据库名为 Datastax Astra。我已经开发了保存数据库文件的逻辑。但是,我仍然收到 1000 毫秒缓冲问题。我查看并尝试过,但没有产生任何结果。

db.ts

import mongoose from "mongoose";
import { driver, createAstraUri } from "stargate-mongoose";

export const connectDb = async () => {
  try {
    const uri = createAstraUri(
      process.env.ASTRA_DB_API_ENDPOINT!,
      process.env.ASTRA_DB_APPLICATION_TOKEN!
    );
    if (mongoose.connection.readyState !== 0) {
      await mongoose.disconnect();
    }
    mongoose.set("autoCreate", true);
    mongoose.setDriver(driver);

    await mongoose
      .connect(uri, { isAstra: true })
      .then((res) => {
        console.log("Connected");
      })
      .catch((r) => {
        console.log(r);
      });
  } catch (error) {
    console.log(error);
  }
};

我在上面的代码中创建了一个到数据库的连接函数,这样我就可以在连接过程中被调用,并在发生错误时引发错误。

这是我的保存电子邮件代码,它创建一个连接并使用 db.ts 文件中的数据库连接函数将数据放入数据库中。

保存_Email.ts

"use server";

import Email from "@/models/email.model";
import { connectDb } from "@/shared/libs/db";

export const saveEmail = async ({
  title,
  content,
  newsLetterOwnerId,
}: {
  title: string;
  content: string;
  newsLetterOwnerId: string;
}) => {
  try {
    await connectDb();
    const email = await Email.findOne({
      title,
      newsLetterOwnerId,
    });

    if (email) {
      await Email.findByIdAndUpdate(email._id, {
        content,
      });
      return { message: "Email updated successfully!" };
    } else {
      await Email.create({
        title,
        content,
        newsLetterOwnerId,
      });
      return { message: "Email saved successfully!" };
    }
  } catch (error) {
    console.log(error);
  }
};

对于电子邮件,我还开发了一个电子邮件架构。下面提供了其代码。

架构

import mongoose from "mongoose";

const { Schema } = mongoose;

const emailSchema = new Schema(
  {
    title: {
      type: String,
    },
    content: {
      type: String,
    },
    newsLetterOwnerId: {
      type: String,
    },
  },
  { timestamps: true }
);

const Email = mongoose.models.Email || mongoose.model("Email", emailSchema);
export default Email;

我尝试在我的在线 Astra 数据库中创建电子邮件集合,但完全不成功。我必须将电子邮件信息在线保存在我的 Astra 数据库中。但事实并非如此,接下来的错误表明了这一点。

Connected
MongooseError: Operation `emails.findOne()` buffering timed out after 10000ms
    at Timeout.<anonymous> (D:\Projects\Portfolio\Newsletter\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185:23)
    at listOnTimeout (node:internal/timers:569:17)
    at process.processTimers (node:internal/timers:512:7)
mongodb mongoose next.js datastax-astra
1个回答
0
投票

针对此案例,有两个设置需要讨论。

  1. bufferCommands 和 bufferTimeoutMS
  2. 服务器选择超时MS

1。 bufferCommands 和 bufferTimeoutMS

bufferCommands 是 mongoose 特定的设置,用于处理与 MongoDB 服务器可能出现的间歇性断开连接。当服务器连接恢复时,它将让应用程序等待并重试模型方法。但是,如果在 bufferTimeoutMS(默认为 10 秒)内连接未恢复,则会超时并抛出错误。

这就是本例中现在发生的情况。应用程序已缓存 - 更具体地说是方法 findOne - 10 秒,然后通过抛出错误而中止。

2。服务器选择超时MS

这是 mongoose 传递给 Mongo 驱动程序的设置。它设置驱动程序尝试寻找服务器来发送任何给定操作的秒数。默认值为 30 秒。

问题:

默认情况下,serverSelectionTimeoutMS 是 bufferTimeoutMS 的 3 倍。因此bufferTimeoutMS将首先到期。这将抑制失败的真正原因,即 serverSelectionTimeoutMS 超时。

现在至少有3个选择,可以让这个案子继续下去

  1. 禁用缓冲区命令
  2. 将 serverSelectionTimeoutMS 降低至 bufferTimeoutMS
  3. 比 serverSelectionTimeoutMS 增加 bufferTimeoutMS

应用选项 1:禁用 bufferCommands - 示例

以下临时设置会让系统等待30秒,然后抛出实际的错误原因。

const schema = new Schema({ /* ... */ }, { bufferCommands: false });

应用选项 2:将 serverSelectionTimeoutMS 降低到 bufferTimeoutMS - 示例

如果您发现选项 1 中的 30 秒等待时间略高于调试所需的时间,请应用此选项。以下临时设置会让系统等待 5 秒,然后抛出与选项 1 类似的错误。

mongoose.connect(uri, { serverSelectionTimeoutMS: 5000 }); // Timeout after 5s instead of 30s

示例代码:选项 1 - 30 秒后抛出连接错误

// Please note there is no MongoDB server at the given URL

import mongoose, { Schema } from 'mongoose';

await main().catch((err) => {
   console.log(`Error thrown: ${new Date()}`);
   console.log(err);
});

mongoose.connection.on('error', (err) => { console.log(err);});

async function main() {
   const uri = 'mongodb://127.1.0.1:27017/test';

   console.log(`Connecting: ${new Date()}`);
   await mongoose.connect(uri);

   const someSchema = new Schema({ somekey: String }, { bufferCommands: false });
   const SomeModel = mongoose.model('SomeModel', someSchema);
   await SomeModel.find();
}
   
OUTPUT: Connection error thrown after 30 seconds

Connecting. : ...   13:37:15 hh:mm:ss ...
Error thrown: ...   13:37:45 hh:mm:ss ...
Error: MongooseServerSelectionError: connection timed out
…

示例代码:选项 2 - 5 秒后抛出连接错误

// Please note there is no MongoDB server at the given URL

import mongoose, { Schema } from 'mongoose';

await main().catch((err) => {
   console.log(`Erron thrown: ${new Date()}`);    
   console.log(err);
});

mongoose.connection.on('error', (err) => {
console.log(err);
});

async function main() {
   const uri = 'mongodb://127.1.0.1:27017/test';

   console.log(`Connecting: ${new Date()}`);
   await mongoose.connect(uri, {
   serverSelectionTimeoutMS: 5000,
   });

   const someSchema = new Schema({ somekey: String });
   const SomeModel = mongoose.model('SomeModel', someSchema);
   await SomeModel.find();
}

OUTPUT: Connection error thrown after 5 seconds

Connecting. : ... 13:33:35 hh:mm:ss ...
Error thrown: ... 13:33:40 hh:mm:ss ...
Error: MongooseServerSelectionError: Server selection timed out after 5000 ms
...

注意事项和要求:

请注意,此处讨论的选项仅用于调试目的。一旦找到连接问题,这方面的更改将被恢复。

要根据应用程序的需要进行永久性更改,请在此处查看原始文档:

  1. https://mongoosejs.com/docs/connections.html
  2. https://mongoosejs.com/docs/guide.html.

谢谢

我们做最好的4你

© www.soinside.com 2019 - 2024. All rights reserved.