Akka single point of failure - scala

I want to create a system that will not have a single point of failure.
I was under the impression that routers are the tool for doing that but I'm not sure it works as I would expect.
This is the entry point of my program :
object Main extends App{
val system = ActorSystem("mySys", ConfigFactory.load("application"))
val router = system.actorOf(
ClusterRouterPool(RoundRobinPool(0), ClusterRouterPoolSettings(
totalInstances = 2, maxInstancesPerNode = 1,
allowLocalRoutees = false, useRole = Some("testActor"))).props(Props[TestActor]),
name = "testActors")
}
And this is the code for running the remote ActorSystem(so the router could deploy the TestActor code to the remote nodes):
object TestActor extends App{
val system = ActorSystem("mySys", ConfigFactory.load("application").getConfig("testactor1"))
case object PrintRouterPath
}
I'm running this twice, once with testactor1 and once with testactor2.
TestActor code:
class TestActor extends Actor with ActorLogging{
implicit val ExecutionContext = context.dispatcher
context.system.scheduler.schedule(10000 milliseconds, 30000 milliseconds,self, PrintRouterPath)
override def receive: Receive = {
case PrintRouterPath =>
log.info(s"router is on path ${context.parent}")
}
}
And application.conf
akka{
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2552
}
}
cluster {
seed-nodes = [
"akka.tcp://mySys#127.0.0.1:2552"
"akka.tcp://mySys#127.0.0.1:2553"
"akka.tcp://mySys#127.0.0.1:2554"]
auto-down-unreachable-after = 20s
}
}
testactor1{
akka{
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2554
}
}
cluster {
roles.1 = "testActor"
seed-nodes = [
"akka.tcp://mySys#127.0.0.1:2552"
"akka.tcp://mySys#127.0.0.1:2553"
"akka.tcp://mySys#127.0.0.1:2554"]
auto-down-unreachable-after = 20s
}
}
}
testactor2{
akka{
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2553
}
}
cluster {
roles.1 = "testActor"
seed-nodes = [
"akka.tcp://mySys#127.0.0.1:2552"
"akka.tcp://mySys#127.0.0.1:2553"
"akka.tcp://mySys#127.0.0.1:2554"]
auto-down-unreachable-after = 20s
}
}
}
Now the problem is that when the process that started the router is killed, the actors that are running the code of TestActor, are not receiving any messages(the messages that the scheduler sends), I would have expect that the router will be deployed on another seed node in the cluster and the actors will be recovered. Is this possible? or is there any other way of implementing this flow and not having a single point of failure?

I think that, by deploying the router on only one node you are setting up a master-slave cluster, where the master is a single point of failure by definition.
From what I understand (looking at the docs), a router can be cluster-aware in the sense that it can deploy (pool mode) or lookup (group mode) routees on nodes in the cluster. The router itself will not react to failure by spawning somewhere else in the cluster.
I believe you have 2 options:
make use of multiple routers to make you system more fault-tolerant. Routees can either be shared (group mode) or not (pool mode) between routers.
make use of the Cluster Singleton pattern - which allows for a master-slave configuration where the master will be automatically re-spawned in case of failure. In relation to your example, note that this behaviour is achieved by having an actor (ClusterSingletonManager) deployed in each node. This actor has the purpose of working out if the chosen master needs to be respawned and where. None of this logic is in place in case of cluster-aware router like the one you setup.
You can find examples of multiple cluster setups in this Activator sample.

i tested two approaches, first using your code with ClusterRouterPool
Like you said when the process that started the router is killed, TestActor not receive more messages.
While reading the documentation and testing , if you change in application.conf :
`auto-down-unreachable-after = 20s`
for this
`auto-down-unreachable-after = off`
the TestActor keep receiving the messages, although in the log the following message appears(i don`t know how to put the log here, sorry):
[WARN] [01/30/2017 17:20:26.017] [mySys-akka.remote.default-remote-dispatcher-5] [akka.tcp://mySys#127.0.0.1:2554/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FmySys%40127.0.0.1%3A2552-0] Association with remote system [akka.tcp://mySys#127.0.0.1:2552] has failed, address is now gated for [5000] ms. Reason: [Association failed with [akka.tcp://mySys#127.0.0.1:2552]] Caused by: [Connection refused: /127.0.0.1:2552]
[INFO] [01/30/2017 17:20:29.860] [mySys-akka.actor.default-dispatcher-4] [akka.tcp://mySys#127.0.0.1:2554/remote/akka.tcp/mySys#127.0.0.1:2552/user/testActors/c1] router is on path Actor[akka.tcp://mySys#127.0.0.1:2552/user/testActors#-1120251475]
[WARN] [01/30/2017 17:20:32.016] [mySys-akka.remote.default-remote-dispatcher-5]
And in the case the MainApp is restarted the log works normally without warning or errors
MainApp Log :
[INFO] [01/30/2017 17:23:32.756] [mySys-akka.actor.default-dispatcher-2] [akka.cluster.Cluster(akka://mySys)] Cluster Node [akka.tcp://mySys#127.0.0.1:2552] - Welcome from [akka.tcp://mySys#127.0.0.1:2554]
TestActor Log:
INFO] [01/30/2017 17:23:21.958] [mySys-akka.actor.default-dispatcher-14] [akka.cluster.Cluster(akka://mySys)] Cluster Node [akka.tcp://mySys#127.0.0.1:2554] - New incarnation of existing member [Member(address = akka.tcp://mySys#127.0.0.1:2552, status = Up)] is trying to join. Existing will be removed from the cluster and then new member will be allowed to join.
[INFO] [01/30/2017 17:23:21.959] [mySys-akka.actor.default-dispatcher-14] [akka.cluster.Cluster(akka://mySys)] Cluster Node [akka.tcp://mySys#127.0.0.1:2554] - Marking unreachable node [akka.tcp://mySys#127.0.0.1:2552] as [Down]
[INFO] [01/30/2017 17:23:22.454] [mySys-akka.actor.default-dispatcher-2] [akka.cluster.Cluster(akka://mySys)] Cluster Node [akka.tcp://mySys#127.0.0.1:2554] - Leader can perform its duties again
[INFO] [01/30/2017 17:23:22.461] [mySys-akka.actor.default-dispatcher-2] [akka.cluster.Cluster(akka://mySys)] Cluster Node [akka.tcp://mySys#127.0.0.1:2554] - Leader is removing unreachable node [akka.tcp://mySys#127.0.0.1:2552]
[INFO] [01/30/2017 17:23:32.728] [mySys-akka.actor.default-dispatcher-4] [akka.cluster.Cluster(akka://mySys)] Cluster Node [akka.tcp://mySys#127.0.0.1:2554] - Node [akka.tcp://mySys#127.0.0.1:2552] is JOINING, roles []
[INFO] [01/30/2017 17:23:33.457] [mySys-akka.actor.default-dispatcher-14] [akka.cluster.Cluster(akka://mySys)] Cluster Node [akka.tcp://mySys#127.0.0.1:2554] - Leader is moving node [akka.tcp://mySys#127.0.0.1:2552] to [Up]
[INFO] [01/30/2017 17:23:37.925] [mySys-akka.actor.default-dispatcher-19] [akka.tcp://mySys#127.0.0.1:2554/remote/akka.tcp/mySys#127.0.0.1:2552/user/testActors/c1] router is on path Actor[akka.tcp://mySys#127.0.0.1:2552/user/testActors#-630150507]
The other approach is to use ClusterRouterGroup, because the routees are shared among the nodes of the cluster
Group - router that sends messages to the specified path using actor selection The routees can be shared among routers running on different nodes in the cluster. One example of a use case for this type of router is a service running on some backend nodes in the cluster and used by routers running on front-end nodes in the cluster.
Pool - router that creates routees as child actors and deploys them on remote nodes. Each router will have its own routee instances. For example, if you start a router on 3 nodes in a 10-node cluster, you will have 30 routees in total if the router is configured to use one instance per node. The routees created by the different routers will not be shared among the routers. One example of a use case for this type of router is a single master that coordinates jobs and delegates the actual work to routees running on other nodes in the cluster.
The Main App
object Main extends App {
val system = ActorSystem("mySys", ConfigFactory.load("application.conf"))
val routerGroup = system.actorOf(
ClusterRouterGroup(RoundRobinGroup(Nil), ClusterRouterGroupSettings(
totalInstances = 2, routeesPaths = List("/user/testActor"),
allowLocalRoutees = false, useRole = Some("testActor"))).props(),
name = "testActors")
}
you must start the TestActor in each remote node
object TestActor extends App{
val system = ActorSystem("mySys", ConfigFactory.load("application").getConfig("testactor1"))
system.actorOf(Props[TestActor],"testActor")
case object PrintRouterPath
}
http://doc.akka.io/docs/akka/2.4/scala/cluster-usage.html#Router_with_Group_of_Routees
The routee actors should be started as early as possible when starting the actor system, because the router will try to use them as soon as the member status is changed to 'Up'.
I hope it helps you

Related

Confluent for Kubernetes can't access kafka externally

I'm trying to create an external access about confluent-kafka from an AKS cluster. I've been able to connect with control center with an Ingress but i can't create the external access from kafka.
I added this to spec of kafka:
listeners:
external:
externalAccess:
type: loadBalancer
loadBalancer:
domain: lb.example.it
advertisedPort: 39093
and it creates two load-balancer services. Then i added the external IPs on my etc/hosts file:
20.31.10.27 kafka.lb.example.it
20.31.9.167 b0.lb.example.it
But when i ceate a nodejs producer i don't know what to put into broker:
const { Kafka } = require('kafkajs')
const kafka = new Kafka({
clientId: 'my-app',
brokers: ['kafka.lb.example.it:39093']
})
const producer = kafka.producer()
console.log("produced")
const asyncOperation = async () => {
console.log("connecting")
await producer.connect()
console.log("connected")
let i = 0
try{
while(true){
await producer.send({
topic: 'topic_prova3',
messages: [
{
key: JSON.stringify("hello"),
value: JSON.stringify({"NUM":i}),
},
]
})
await producer.send({
topic: 'topic_prova3',
messages: [
{
value: JSON.stringify({"NUMERO":i.toString()}),
},
]
})
console.log("sended")
i++
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
catch(err){
console.error("error: " + err)
}
await producer.disconnect()
}
asyncOperation();
This is the log of the error:
{"level":"ERROR","timestamp":"2023-01-22T08:43:20.761Z","logger":"kafkajs","message":"[Connection] Connection error: connect ECONNREFUSED 127.0.0.2:9092","broker":"kafka-0.kafka.ckafka.svc.cluster.local:9092","clientId":"my-app","stack":"Error: connect ECONNREFUSED 127.0.0.2:9092\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16)"}
The broker should be kafka.ckafka.svc.cluster.local:9092 , instead of kafka-0.kafka.ckafka.svc.cluster.local:9092 but it does it automatically
The load balancer appears to be working (it's not throwing unknown host exception), and it returned a cluster local broker address. See above comment that explains why this happens within Kubernetes with Kafka.
You need to modify, or use, the appropriate advertised.listeners port that corresponds to the external LoadBalancer.
from an AKS cluster.
You should use Azure services to create a public DNS route rather than specifically target one IP of your cluster for any given service in /etc/hosts; especially when you'd deploy multiple replicas of the Kafka pod.

How to connect to Mongo DB in Docker from Scala Play Framework?

I have a Mongo DB Docker container running on 192.168.0.229. From another computer, I can access it via:
> mongo "mongodb://192.168.0.229:27017/test"
But when I add that configuration string (host="192.168.0.229") to my Play Framework app, I get a timeout error:
[debug] application - Login Form Success: UserData(larry#gmail.com,testPW)
[error] p.a.h.DefaultHttpErrorHandler -
! #7m7kggikl - Internal server error, for (POST) [/] ->
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[TimeoutException: Future timed out after [30 seconds]]]
In the past, the connection was successful with host="localhost" and even an Atlas cluster (host="mycluster.gepld.mongodb.net") for the hostname, so there were no problems connecting previously with the same code. For some reason, Play Framework does not want to connect to this endpoint!
Could it be because the hostname is an IP address? Or, maybe Play/ Akka is doing something under the covers to stop the connection (or something to make Mongo/Docker refuse to accept it?)?
I'm using this driver:
"org.mongodb.scala" %% "mongo-scala-driver" % "4.4.0"
Perhaps I should switch to the Reactive Scala Driver? Any help would be appreciated.
Clarifications:
The Mongo DB Docker container is running on a linux machine on my local network. This container is reachable from within my local network at 192.168.0.229. The goal is to set my Play Framework app configuration to point to the DB at this address, so that as long as the Docker container is running, I can develop from any computer on my local network. Currently, I am able to access the container through the mongo shell on any computer:
> mongo "mongodb://192.168.0.229:27017/test"
I have a Play Framework app with the following in the Application.conf:
datastore {
# Dev
host: "192.168.0.229"
port: 27017
dbname: "test"
user: ""
password: ""
}
This data is used in a connection helper file called DataStore.scala:
package model.db.mongo
import org.mongodb.scala._
import utils.config.AppConfiguration
trait DataStore extends AppConfiguration {
lazy val dbHost = config.getString("datastore.host")
lazy val dbPort = config.getInt("datastore.port")
lazy val dbUser = getConfigString("datastore.user", "")
lazy val dbName = getConfigString("datastore.dbname", "")
lazy val dbPasswd = getConfigString("datastore.password", "")
//MongoDB Atlas Method (Localhost if DB User is empty)
val uri: String = s"mongodb+srv://$dbUser:$dbPasswd#$dbHost/$dbName?retryWrites=true&w=majority"
//val uri: String = "mongodb+svr://192.168.0.229:27017/?compressors=disabled&gssapiServiceName=mongodb"
System.setProperty("org.mongodb.async.type", "netty")
val mongoClient: MongoClient = if (getConfigString("datastore.user", "").isEmpty()) MongoClient() else MongoClient(uri)
print(mongoClient.toString)
print(mongoClient.listDatabaseNames())
val database: MongoDatabase = mongoClient.getDatabase(dbName)
def close = mongoClient.close() //Do this when logging out
}
When you start the app, you open localhost:9000 which is simply a login form. When you fill out the data that corresponds with the data in the users collection, the Play app times out:
[error] p.a.h.DefaultHttpErrorHandler -
! #7m884abc4 - Internal server error, for (POST) [/] ->
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[TimeoutException: Future timed out after [30 seconds]]]
at play.api.http.HttpErrorHandlerExceptions$.$anonfun$convertToPlayException$2(HttpErrorHandler.scala:381)
at scala.Option.map(Option.scala:242)
at play.api.http.HttpErrorHandlerExceptions$.convertToPlayException(HttpErrorHandler.scala:380)
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:373)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:264)
at play.core.server.AkkaHttpServer$$anonfun$2.applyOrElse(AkkaHttpServer.scala:430)
at play.core.server.AkkaHttpServer$$anonfun$2.applyOrElse(AkkaHttpServer.scala:422)
at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:454)
at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:63)
at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:100)
Caused by: java.util.concurrent.TimeoutException: Future timed out after [30 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.tryAwait0(Promise.scala:212)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:225)
at scala.concurrent.Await$.$anonfun$result$1(package.scala:201)
at akka.dispatch.MonitorableThreadFactory$AkkaForkJoinWorkerThread$$anon$3.block(ThreadPoolBuilder.scala:174)
at java.base/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3118)
at akka.dispatch.MonitorableThreadFactory$AkkaForkJoinWorkerThread.blockOn(ThreadPoolBuilder.scala:172)
at akka.dispatch.BatchingExecutor$BlockableBatch.blockOn(BatchingExecutor.scala:116)
at scala.concurrent.Await$.result(package.scala:124)
at model.db.mongo.DataHelpers$ImplicitObservable.headResult(DataHelpers.scala:27)
at model.db.mongo.DataHelpers$ImplicitObservable.headResult$(DataHelpers.scala:27)
The call to the Users collection is defined in UserAccounts.scala:
case class UserAccount(_id: String, fullname: String, username: String, password: String)
object UserAccount extends DataStore {
val logger: Logger = Logger("database")
//Required for using Case Classes
val codecRegistry = fromRegistries(fromProviders(classOf[UserAccount]), DEFAULT_CODEC_REGISTRY)
//Using Case Class to get a collection
val coll: MongoCollection[UserAccount] = database.withCodecRegistry(codecRegistry).getCollection("users")
//Using Document to get a collection
val listings: MongoCollection[Document] = database.getCollection("users")
def isValidLogin(username: String, password: String): Boolean = {
findUser(username) match {
case Some(u: UserAccount) => if(password.equals(u.password)) { true } else {false }
case None => false
}
}
Just an FYI if anyone runs into this problem. I had a bad line in my DataStore.scala file:
val mongoClient: MongoClient = if (getConfigString("datastore.user", "").isEmpty()) MongoClient() else MongoClient(uri)
Since I was trying to connect without a username (there's no auth on my test db), the above line was saying, "If there's no username, you must be trying to connect to the default MongoClient() location, which is localhost". My mistake.
I simply changed the above line to this:
val mongoClient: MongoClient = MongoClient(uri)

Connect two machines in AKKA remotely ,connection refused

I'm new to akka and wanted to connect two PC using akka remotely just to run some code in both as (2 actors). I had tried the example in akka doc. But what I really do is to add the 2 IP addresses into config file I always get this error?
First machine give me this error:
[info] [ERROR] [11/20/2018 13:58:48.833]
[ClusterSystem-akka.remote.default-remote-dispatcher-6]
[akka.remote.artery.Association(akka://ClusterSystem)] Outbound
control stream to [akka://ClusterSystem#192.168.1.2:2552] failed.
Restarting it. Handshake with [akka://ClusterSystem#192.168.1.2:2552]
did not complete within 20000 ms
(akka.remote.artery.OutboundHandshake$HandshakeTimeoutException:
Handshake with [akka://ClusterSystem#192.168.1.2:2552] did not
complete within 20000 ms)
And second machine:
Exception in thread "main"
akka.remote.RemoteTransportException: Failed to bind TCP to
[192.168.1.3:2552] due to: Bind failed because of
java.net.BindException: Cannot assign requested address: bind
Config file content :
akka {
actor {
provider = cluster
}
remote {
artery {
enabled = on
transport = tcp
canonical.hostname = "192.168.1.3"
canonical.port = 0
}
}
cluster {
seed-nodes = [
"akka://ClusterSystem#192.168.1.3:2552",
"akka://ClusterSystem#192.168.1.2:2552"]
# auto downing is NOT safe for production deployments.
# you may want to use it during development, read more about it in the docs.
auto-down-unreachable-after = 120s
}
}
# Enable metrics extension in akka-cluster-metrics.
akka.extensions=["akka.cluster.metrics.ClusterMetricsExtension"]
# Sigar native library extract location during tests.
# Note: use per-jvm-instance folder when running multiple jvm on one host.
akka.cluster.metrics.native-library-extract-folder=${user.dir}/target/native
First of all, you don't need to add cluster configuration for AKKA remoting. Both the PCs or nodes should be enabled remoting with a concrete port instead of "0" that way you know which port to connect.
Have below configurations
PC1
akka {
actor {
provider = remote
}
remote {
artery {
enabled = on
transport = tcp
canonical.hostname = "192.168.1.3"
canonical.port = 19000
}
}
}
PC2
akka {
actor {
provider = remote
}
remote {
artery {
enabled = on
transport = tcp
canonical.hostname = "192.168.1.4"
canonical.port = 18000
}
}
}
Use below actor path to connect any actor in remote from PC1 to PC2
akka://<PC2-ActorSystem>#192.168.1.4:18000/user/<actor deployed in PC2>
Use below actor path to connect from PC2 to PC1
akka://<PC2-ActorSystem>#192.168.1.3:19000/user/<actor deployed in PC1>
Port numbers and IP address are samples.

akka cluster Connection refused: address is now > gated for [5000] ms

I have a cluster with 2 workers and 1 master. the cluster is implemented with Akka and Scala.
When i killed the worker and try to run it again with the following command:
java -Xms3500M -Xmx3500M -Dlog_file_name=worker1
"-Dconfig.file=F:\cluster\application.conf" -cp cluster.jar
knowmail.Worker worker1 2551
I get the following error:
Connection refused
Association with remote system
[akka.tcp://ClusterSystem#xxxxxx:2552] has failed, address is now
gated for [5000] ms. Reason: [As
kka.tcp://ClusterSystem#xxxx:2552]] Caused by: [Connection
refused: no further information: /xxxx:2552]
a configuration of cluster:
remote {
log-remote-lifecycle-events = off
log-received-messages = on
log-sent-messages = on
netty.tcp {
hostname = "xxxxxx"
port = 8888
bind-hostname = 0.0.0.0
bind-port = 8888
}
}
cluster {
seed-nodes = [
"akka.tcp://ClusterSystem#xxxxx:2551",
"akka.tcp://ClusterSystem#xxxxxx:2552"]
auto-down-unreachable-after = 20s
}
http.client.parsing.max-content-length = infinite
}
Did anyone encountered this error and solved it?
This happens when I start one of the seed nodes/workers before the other seed node has been started.
So one seed node is looking for the other and reports the following error of:
akka.tcp://ClusterSystem#10.5.2.10:2552] has failed, address is now
gated for [5000] ms.

How do I resolve a MongoDB timeout error when connecting via the Scala Play! framework?

I am connecting to MongoDB while using the Scala Play! framework. I end up getting this timeout error:
! #6j672dke5 - Internal server error, for (GET) [/accounts] ->
play.api.Application$$anon$1: Execution exception[[MongoTimeoutException: Timed out while waiting to connect after 10000 ms]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10-2.2.1.jar:2.2.1]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10-2.2.1.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$12$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:165) [play_2.10-2.2.1.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$12$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:162) [play_2.10-2.2.1.jar:2.2.1]
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33) [scala-library-2.10.4.jar:na]
at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:185) [scala-library-2.10.4.jar:na]
Caused by: com.mongodb.MongoTimeoutException: Timed out while waiting to connect after 10000 ms
at com.mongodb.BaseCluster.getDescription(BaseCluster.java:131) ~[mongo-java-driver-2.12.3.jar:na]
at com.mongodb.DBTCPConnector.getClusterDescription(DBTCPConnector.java:396) ~[mongo-java-driver-2.12.3.jar:na]
at com.mongodb.DBTCPConnector.getType(DBTCPConnector.java:569) ~[mongo-java-driver-2.12.3.jar:na]
at com.mongodb.DBTCPConnector.isMongosConnection(DBTCPConnector.java:370) ~[mongo-java-driver-2.12.3.jar:na]
at com.mongodb.Mongo.isMongosConnection(Mongo.java:645) ~[mongo-java-driver-2.12.3.jar:na]
at com.mongodb.DBCursor._check(DBCursor.java:454) ~[mongo-java-driver-2.12.3.jar:na]
Here is my Scala code for connecting to the database:
//models.scala
package models.mongodb
//imports
package object mongoContext {
//context stuff
val client = MongoClient(current.configuration.getString("mongo.host").toString())
val database = client(current.configuration.getString("mongo.database").toString())
}
Here is the actual model that is making the connection:
//google.scala
package models.mongodb
//imports
case class Account(
id: ObjectId = new ObjectId,
name: String
)
object AccountDAO extends SalatDAO[Account, ObjectId](
collection = mongoContext.database("accounts")
)
object Account {
def all(): List[Account] = AccountDAO.find(MongoDBObject.empty).toList
}
Here's the Play! framework MongoDB conf information:
# application.conf
# mongodb connection details
mongo.host="localhost"
mongo.port=27017
mongo.database="advanced"
Mongodb is running on my local machine. I can connect to it by typing mongo at the terminal window. Here's the relevant part of the conf file:
# mongod.conf
# Where to store the data.
# Note: if you run mongodb as a non-root user (recommended) you may
# need to create and set permissions for this directory manually,
# e.g., if the parent directory isn't mutable by the mongodb user.
dbpath=/var/lib/mongodb
#where to log
logpath=/var/log/mongodb/mongod.log
logappend=true
#port = 27017
# Listen to local interface only. Comment out to listen on all interfaces.
#bind_ip = 127.0.0.1
So what's causing this timeout error and how do I fix it? Thanks!
I figured out that I needed to change:
val client = MongoClient(current.configuration.getString("mongo.host").toString())
val database = client(current.configuration.getString("mongo.database").toString())
to:
val client = MongoClient(conf.getString("mongo.host"))
val database = client(conf.getString("mongo.database"))