Mongoose `findOne` 操作在 10000 毫秒后超时

时间:2021-02-26 06:57:59

标签: node.js mongodb typescript mongoose atlas

这个错误真的很令人沮丧,特别是因为它是间歇性的(它来来去去)。我正在使用带有 express 和 typescript 的猫鼬,并且我正在连接到 MongoDB 地图集上的数据库。这会导致糟糕的用户体验,而且不是很酷。显示的错误消息显示 Operation wallets.findOne() buffering timed out after 10000ms。有时应用程序运行良好并按预期执行所有操作,但此错误在某些时候突然出现。下面是我的代码,如果你通读它,你会发现我正在使用 async await。

import mongoose from "mongoose";
import { Wallet } from "../../core/interfaces";
import { Tokenizers } from "../../core/utils";

export class WalletModel {
  model: mongoose.Model<any>;

  constructor() {
    this.define();
  }

  private define() {
    this.model = mongoose.model(
      "Wallet",
      new mongoose.Schema({
        encryptedPrivateKey: String,
        encryptedWallet: {
          type: String,
          required: true
        }
      })
    );
  }

  async create(wallet: Wallet, privateKey: string): Promise<Wallet> {
    const encryptedWallet = Tokenizers.encryptWallet(wallet);
    const walletModel: any = await this.model.create({
      encryptedPrivateKey: Tokenizers.encryptPrivateKey(
        privateKey,
        wallet.publicKey
      ),
      encryptedWallet
    });
    const decryptedWallet: Wallet = Tokenizers.decryptWallet(
      walletModel.encryptedWallet,
      wallet.privateKey
    );
    return Promise.resolve(decryptedWallet);
  }

  async getWallet(privateKey: string, publicKey: string): Promise<Wallet> {
    const encPrivateKey: string = Tokenizers.encryptPrivateKey(
      privateKey,
      publicKey
    );
    // Below find utilizes the indexing created on encryptedPrivateKey field
    // and is way faster than linear search on whole collection
    const encWallet: mongoose.Document & {
      encryptedPrivateKey: string;
      encryptedWallet: string;
    } = (await this.model
      .findOne({
        encryptedPrivateKey: encPrivateKey
      })
      .lean()) as mongoose.Document & {
      encryptedPrivateKey: string;
      encryptedWallet: string;
    };
    const encryptedWallet: string = encWallet.encryptedWallet;
    const decryptedWallet: Wallet = Tokenizers.decryptWallet(
      encryptedWallet,
      privateKey
    );
    return Promise.resolve(decryptedWallet);
  }

  async findByPrivateKey(privateKey: string): Promise<Wallet> {
    let wallet: Wallet = null;
    const allWallets = (await this.model.find().lean()) as any;

    for (const doc of allWallets) {
      const pk = Tokenizers.decryptPrivateKey(doc.encryptedPrivateKey);
      if (pk === privateKey)
        wallet = Tokenizers.decryptWallet(doc.encryptedWallet, privateKey);
    }

    return Promise.resolve(wallet);
  }

  async updateWallet(privateKey: string, newWallet: Wallet): Promise<Wallet> {
    // const allWallets = await this.model.find();
    let w: Wallet = null;
    const updatedWallet = (await this.model
      .findOneAndUpdate(
        {
          encryptedPrivateKey: Tokenizers.encryptPrivateKey(
            privateKey,
            newWallet.publicKey
          )
        },
        {
          encryptedWallet: Tokenizers.encryptWallet(newWallet)
        },
        {
          new: true
        }
      )
      .lean()) as mongoose.Document & {
      encryptedWallet: string;
      encryptedPrivateKey: string;
    };
    w = Tokenizers.decryptWallet(updatedWallet.encryptedWallet, privateKey);
    return Promise.resolve(w);
  }
}

这是我启动所有服务器并建立连接的 index.ts 文件的内容:

import express from "express";
import mongoose from "mongoose";
import config from "./config";
import { Environment } from "./env";

let app: express.Application = express();
const port = process.env.PORT || 7890;

app = config(app);

app.listen(port, async () => {
  console.log(`Server listening on port ${port} in ${process.env.NODE_ENV}`);
  const mongo = await mongoose.connect(
    Environment.MONGO_URI[process.env.NODE_ENV],
    {
      useNewUrlParser: true,
      useFindAndModify: false,
      useCreateIndex: true
    }
  );
  if (mongo) console.log("Connected to mongodb");
});

// Export app for tests
export default app;

1 个答案:

答案 0 :(得分:0)

尝试在您的猫鼬模型中添加 index: true 。如果数据库记录很大,也会发生这种情况,因此创建索引可以帮助快速找到文档。