mongo 没有 ping函数 所以需要参照PDO的写法, findOne Throws MongoConnectionException if it cannot reach the database.
// mongo instance
function getMongoCollection($col)
{
static $mongoClient, $collection = [];
try {
// init mongoClient
if (!$mongoClient) {
$mongoClient = mongoClientInit();
}
// check mongoClient
if (!is_object($mongoClient) || !method_exists($mongoClient, 'selectCollection')) {
throw new \MongoConnectionException('reconnect mongo failed');
}
// init mongoCollection
if (!isset($collection[$col])) {
$collection[$col] = mongoCollectionInit($mongoClient, $col);
}
// ping mongo
$collection[$col] = mongoPing($collection[$col], $col);
// check mongoPing again
if (!is_object($collection[$col])) {
throw new \MongoConnectionException('reconnect mongo failed');
}
} catch (\MongoConnectionException $e) {
error_log($e->getMessage(), 3, ERROR_LOG);
}
return $collection[$col] ?: null;
}
function mongoPing($collection, $col)
{
try {
// check collection
if (!$collection || !method_exists($collection, 'findOne')) {
throw new \MongoConnectionException('mongo connect failed');
}
// Throws MongoConnectionException if it cannot reach the database.
$collection->findOne([], ['_id' => 1]);
} catch (\MongoConnectionException $e) {
// log
error_log('mongo connect failed and try to reconnect', 3, ERROR_LOG);
// init MongoClient
$mongoClient = mongoClientInit();
// init MongoCollection
if (is_object($mongoClient) && method_exists($mongoClient, 'selectCollection')) {
$collection = mongoCollectionInit($mongoClient, $col);
} else {
$collection = null;
}
}
return $collection;
}
function mongoClientInit()
{
$config = get_config('mongo');
// reconnect mongo 3 times
$mongoClient = null;
$i = 0;
while ($i < 3 && !$mongoClient) {
try {
$mongoClient = new MongoClient($config['dsn']);
} catch (\MongoConnectionException $e) {
$i++;
}
}
return $mongoClient;
}
function mongoCollectionInit($mongoClient, $col)
{
$config = get_config('mongo');
// get MongoCollection object
$i = 0;
$collection = null;
while ($i < 3 && !$collection) {
try {
$collection = $mongoClient->selectCollection($config['db'], $col);
} catch (\Exception $e) {
$i++;
}
}
return $collection;
}