首页 > 解决方案 > 如何在无服务器设置中可靠地连接到 Mongodb?

问题描述

十分之八的事情都连接良好。也就是说,我有时会MongoClient must be connected before calling MongoClient.prototype.db出错。我应该如何更改我的代码以使其可靠地工作(100%)?

我尝试了来自 Now Zeit 平台的创建者之一的代码片段。

我的处理程序

const { send } = require('micro');
const { handleErrors } = require('../../../lib/errors');
const cors = require('../../../lib/cors')();
const qs = require('micro-query');
const mongo = require('../../../lib/mongo');
const { ObjectId } = require('mongodb');

const handler = async (req, res) => {
  let { limit = 5 } = qs(req);

  limit = parseInt(limit);
  limit = limit > 10 ? 10 : limit;

  const db = await mongo();

  const games = await db
    .collection('games_v3')
    .aggregate([
      {
        $match: {
          removed: { $ne: true }
        }
      },
      { $sample: { size: limit } }
    ])
    .toArray();

  send(res, 200, games);
};

module.exports = handleErrors(cors(handler));

我的 mongo 脚本在 lambda 仍然温暖的情况下重用连接:

// Based on: https://spectrum.chat/zeit/now/now-2-0-connect-to-database-on-every-function-invocation~e25b9e64-6271-4e15-822a-ddde047fa43d?m=MTU0NDkxODA3NDExMg==
const MongoClient = require('mongodb').MongoClient;

if (!process.env.MONGODB_URI) {
  throw new Error('Missing env MONGODB_URI');
}

let client = null;

module.exports = function getDb(fn) {
  if (client && !client.isConnected) {
    client = null;
    console.log('[mongo] client discard');
  }

  if (client === null) {
    client = new MongoClient(process.env.MONGODB_URI, {
      useNewUrlParser: true
    });
    console.log('[mongo] client init');
  } else if (client.isConnected) {
    console.log('[mongo] client connected, quick return');
    return client.db(process.env.MONGO_DB_NAME);
  }

  return new Promise((resolve, reject) => {
    client.connect(err => {
      if (err) {
        client = null;
        console.error('[mongo] client err', err);
        return reject(err);
      }

      console.log('[mongo] connected');
      resolve(client.db(process.env.MONGO_DB_NAME));
    });
  });
};

我需要我的处理程序是 100% 可靠的。

标签: node.jsmongodbserverlessvercel

解决方案


  if (client && !client.isConnected) {
    client = null;
    console.log('[mongo] client discard');
  }

此代码可能会导致问题!即使您设置clientnull,该客户端仍然存在,将继续连接到 mongo,不会被垃圾收集,并且其回调连接代码仍将运行,但在其回调client中将引用创建的下一个客户端不一定连接

getDB这种代码的一个常见模式是只从调用中返回一个承诺:

let clientP = null;
function getDb(fn) {
  if (clientP) return clientP;
  clientP = new Promise((resolve, reject) => {
    client = new MongoClient(process.env.MONGODB_URI, {
      useNewUrlParser: true
    });
    client.connect(err => {
      if (err) {
        console.error('[mongo] client err', err);
        return reject(err);
      }

      console.log('[mongo] connected');
      resolve(client.db(process.env.MONGO_DB_NAME));
    });
  });
  return clientP;
};


推荐阅读