Reputation: 876
I am trying to connect my Scala application to a Postgres cluster consisting of one master node and 3 slaves/read replicas. My application.conf looks like this today:
slick {
dbs {
default {
driver = "com.company.division.db.ExtendedPgDriver$"
db {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://"${?DB_ADDR}":"${?DB_PORT}"/"${?DB_NAME}
user = ${?DB_USERNAME}
password = ${?DB_PASSWORD}
}
}
}
}
Based on Postgres' documentation, I can define the master and slaves all in one JDBC URL, which will give me some failover capabilities, like this:
jdbc:postgresql://host1:port1,host2:port2/database
However, if I want to separate my connections by read and write capabilities, I have to define two JDBC URls, like this:
jdbc:postgresql://node1,node2,node3/database?targetServerType=master
jdbc:postgresql://node1,node2,node3/database?targetServerType=preferSlave&loadBalanceHosts=true
How can I define two JDBC URLs within Slick? Should I define two separate entities under slick.dbs, or can my slick.dbs.default.db entity have multiple multiple URLs defined?
Upvotes: 1
Views: 1191
Reputation: 876
Found an answer from Daniel Westheide's blog post. To summarize, it can be done with a DB wrapper class and custom Effect types that provides specific rules to control where read-only queries are directed vs. write queries are directed.
Then your slick file would look like this:
slick {
dbs {
default {
driver = "com.yourdomain.db.ExtendedPgDriver$"
db {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://"${?DB_PORT_5432_TCP_ADDR}":"${?DB_PORT_5432_TCP_PORT}"/"${?DB_NAME}
user = ${?DB_USERNAME}
password = ${?DB_PASSWORD}
}
}
readonly {
driver = "com.yourdomain.db.ExtendedPgDriver$"
db {
driver = "org.postgresql.Driver"
url = ${DB_READ_REPLICA_URL}
user = ${?DB_USERNAME}
password = ${?DB_PASSWORD}
}
}
}
}
And it's up to your DB wrapper class to route queries to either 'default' or 'readonly'
Upvotes: 2