Как надежно подключиться к Mongodb в режиме без сервера? - PullRequest
0 голосов
/ 08 февраля 2019

8 из десяти раз все хорошо соединяется.Тем не менее, я иногда получаю ошибку 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));

Мой скрипт монго, который повторно использует соединение в случае, если лямбда все еще теплая:

// 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% надежным.

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019
  if (client && !client.isConnected) {
    client = null;
    console.log('[mongo] client discard');
  }

Этот код может вызвать проблемы!Даже если вы установите client в null, этот клиент все еще существует, продолжит подключение к 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;
};

0 голосов
/ 22 февраля 2019

У меня была такая же проблема.В моем случае это было вызвано вызовом getDb () до того, как был возвращен предыдущий вызов getDb ().В этом случае я считаю, что client.isConnected возвращает true, хотя он все еще подключается.

Это было вызвано тем, что вы забыли поместить «await» перед вызовом getDb () в одном месте.Я обнаружил, что путем вывода callstack из getDb с помощью:

console.log(new Error().stack);

я не вижу той же проблемы в примере кода в вопросе, хотя она может быть вызвана другим битом кода, который не 'т показано.

...