Hi,
In one akka project, I use reactivemongo to save metadata, I get sometimes the following error :
reactivemongo mongoerror 'no primary node is available
First, I'm using the last version of reactivemongo.
"org.reactivemongo" % "play2-reactivemongo_2.11" % "0.12.0-play24"
I read some topics about this error and I know there are so deprecated functions to not use (like db.collection) so below the code used to communicate with mongodb :
// Scala
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{ Await, Future }
import scala.util.{ Try, Failure, Success }
import scala.concurrent.duration._
// ReactiveMongo
import reactivemongo.api.{ DefaultDB, MongoConnection, MongoDriver }
import reactivemongo.play.json.collection.JSONCollection
// TypeSafe
import com.typesafe.scalalogging._
import com.typesafe.config.ConfigFactory
/**
* Database basic operations.
*/
object Database extends LazyLogging {
/**
* Because we are in a singleton, the drive will be create juste
* once.
*/
private val driver = new MongoDriver
/**
* Create a connection to an existing mongo database name
* @param mongoURI the URI of mongo server
* @param mongoDatabase the mongo database name
* @return a Future with an Option indicating if the connection is
* successful or not.
*/
def createConnection
(
mongoURI : String
) : Try[MongoConnection] =
MongoConnection
.parseURI(mongoURI)
.map(parsedUri => driver.connection(parsedUri))
/**
* Get a collection from reactivemongo
* @param mongoURI the URI of mongo server
* @param mongoDatabase the mongo database name
* @param mongoCollectionName the mongo collection name
*/
def getFutureDatabase
(
mongoConnectionOpt : Try[MongoConnection],
mongoDatabase : String
): Future[DefaultDB] = {
mongoConnectionOpt match {
case Success(connection) =>
connection.database(mongoDatabase)
case Failure(e) =>
logger.info("Error when connectiong to the mongo server -> " + e)
Future { null }
}
}
def getFutureCollection
(
mongoDatabase : Future[DefaultDB],
mongoCollectionName : String
) : Future[JSONCollection] = {
mongoDatabase map (_.collection(mongoCollectionName))
}
The error comes when I try to create a new JSON document like this :
case class BFF_MongoIO(futureCollection: Future[JSONCollection]) extends LazyLogging {
def createRecord(record: CCWBiosRecord): Future[WriteResult] = {
futureCollection flatMap(_.insert(record))
}
I'm using this code in an Akka actors application. I wrote a Main in which I created all the actors of my actor system but also all the mongo requirements to communicate with it my collections :
val mongoURI = config.getString("mongo.uri")
val connectionOpt : Try[MongoConnection] =
Database.createConnection(mongoURI)
/**
* Mongo DB Name
*/
val mongoDBName = config.getString("mongo.database")
def futureDB : Future[DefaultDB] =
Database.getFutureDatabase(connectionOpt,mongoDBName)
/**
* Reactivemongo collection name with records metadata
*/
def bffCollectionName = config.getString("mongo.collection_bff")
logger.info("bff collection name = " + bffCollectionName)
def eventCollectionName = config.getString("mongo.collection_bff_events")
logger.info("bff events collection name = " + eventCollectionName)
def futureBFFCollection : Future[JSONCollection] =
Database.getFutureCollection(futureDB, bffCollectionName)
def futureEventsCollection : Future[JSONCollection] =
Database.getFutureCollection(futureDB, eventCollectionName)
val listener =
system
.actorOf(KafkaStartStreamListener.props(kafkaProps, kafkaPollTimeout, streamingListener, kafkaEventsListener, futureBFFCollection, None), name = "UP_DOWN_Listener_Actor")
In the above actor, I'm calling the function createRecord like this :
val futureCreate = bff_MongoIO.createRecord(record)
futureCreate onComplete {
case Success(s) => ()
case Failure(e) =>
log.error("Error when create record {} ", e)
}
In a previous version of my code, I was using an old version of play2-reactivemongo_2.11 (0.11.4) and when I updated this lib version, the error came less often.
But what I want to know is that if I'm doing a wrong thing about the way to create the mongodb collections or their uses. From the last mongodb documentation, I read that dababase and collections should be assisgned to def and not val. In my case, I'm doing this but I wrapped them in a Future, is it change something in the reactivemongo side ?