Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Commit

Permalink
refactor connectionpools into 'databases'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ed Ceaser committed Feb 11, 2010
1 parent 6fd1a0f commit 124e98d
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 107 deletions.
2 changes: 1 addition & 1 deletion ivy/ivy.xml
@@ -1,7 +1,7 @@
<ivy-module version="1.0" xmlns:e="http://ant.apache.org/ivy/extra">
<info organisation="com.twitter"
module="querulous"
revision="1.0.0"
revision="1.1.0"
e:buildpackage="com.twitter.querulous"
e:testclass="com.twitter.querulous.TestRunner"
e:jarclassname="com.twitter.querulous.Main"
Expand Down

This file was deleted.

This file was deleted.

@@ -1,20 +1,20 @@
package com.twitter.querulous.connectionpool
package com.twitter.querulous.database

import java.sql.{Connection, SQLException}
import org.apache.commons.dbcp.{PoolableConnectionFactory, DriverManagerConnectionFactory, PoolingDataSource}
import org.apache.commons.pool.impl.{GenericObjectPool, StackKeyedObjectPoolFactory}
import com.twitter.xrayspecs.Duration

class ApacheConnectionPoolFactory(
class ApachePoolingDatabaseFactory(
minOpenConnections: Int,
maxOpenConnections: Int,
checkConnectionHealthWhenIdleFor: Duration,
maxWaitForConnectionReservation: Duration,
checkConnectionHealthOnReservation: Boolean,
evictConnectionIfIdleFor: Duration) extends ConnectionPoolFactory {
evictConnectionIfIdleFor: Duration) extends DatabaseFactory {

def apply(dbhosts: List[String], dbname: String, username: String, password: String) = {
val pool = new ApacheConnectionPool(
val pool = new ApachePoolingDatabase(
dbhosts,
dbname,
username,
Expand All @@ -29,7 +29,7 @@ class ApacheConnectionPoolFactory(
}
}

class ApacheConnectionPool(
class ApachePoolingDatabase(
dbhosts: List[String],
dbname: String,
username: String,
Expand All @@ -39,7 +39,7 @@ class ApacheConnectionPool(
checkConnectionHealthWhenIdleFor: Duration,
maxWaitForConnectionReservation: Duration,
checkConnectionHealthOnReservation: Boolean,
evictConnectionIfIdleFor: Duration) extends ConnectionPool {
evictConnectionIfIdleFor: Duration) extends Database {

Class.forName("com.mysql.jdbc.Driver")

Expand Down
@@ -1,12 +1,12 @@
package com.twitter.querulous.connectionpool
package com.twitter.querulous.database

import java.sql.Connection

trait ConnectionPoolFactory {
def apply(dbhosts: List[String], dbname: String, username: String, password: String): ConnectionPool
trait DatabaseFactory {
def apply(dbhosts: List[String], dbname: String, username: String, password: String): Database
}

trait ConnectionPool {
trait Database {
def reserve(): Connection

def release(connection: Connection)
Expand Down
@@ -0,0 +1,18 @@
package com.twitter.querulous.database

import scala.collection.mutable

class MemoizingDatabaseFactory(databaseFactory: DatabaseFactory) extends DatabaseFactory {
private val databases = new mutable.HashMap[String, Database]

def apply(dbhosts: List[String], dbname: String, username: String, password: String) = synchronized {
databases.getOrElseUpdate(
dbhosts.first + "/" + dbname,
databaseFactory(dbhosts, dbname, username, password))
}

def close() {
for ((name, pool) <- databases) pool.close()
databases.clear()
}
}
@@ -0,0 +1,32 @@
package com.twitter.querulous.database

import java.sql.Connection

class StatsCollectingDatabaseFactory(
databaseFactory: DatabaseFactory,
stats: StatsCollector) extends DatabaseFactory {

def apply(dbhosts: List[String], dbname: String, username: String, password: String): Database = {
new StatsCollectingDatabase(databaseFactory(dbhosts, dbname, username, password), stats)
}
}

class StatsCollectingDatabase(pool: Database, stats: StatsCollector)
extends Database {

override def reserve(): Connection = {
stats.time("connection-pool-reserve-timing") {
pool.reserve()
}
}

override def release(connection: Connection) = {
stats.time("connection-pool-release-timing") {
pool.release(connection)
}
}

override def close() = {
pool.close()
}
}
Expand Up @@ -2,14 +2,14 @@ package com.twitter.querulous.evaluator

import java.sql.ResultSet
import com.twitter.querulous.query.SqlQueryFactory
import com.twitter.querulous.connectionpool.ApacheConnectionPoolFactory
import com.twitter.querulous.database.ApachePoolingDatabaseFactory
import com.twitter.xrayspecs.TimeConversions._

object QueryEvaluator extends QueryEvaluatorFactory {
def apply(dbhosts: List[String], dbname: String, username: String, password: String) = {
val queryFactory = new SqlQueryFactory
val connectionPoolFactory = new ApacheConnectionPoolFactory(10, 10, 1.second, 10.millis, false, 0.seconds)
val queryEvaluatorFactory = new StandardQueryEvaluatorFactory(connectionPoolFactory, queryFactory)
val databaseFactory = new ApachePoolingDatabaseFactory(10, 10, 1.second, 10.millis, false, 0.seconds)
val queryEvaluatorFactory = new StandardQueryEvaluatorFactory(databaseFactory, queryFactory)
queryEvaluatorFactory(dbhosts, dbname, username, password)
}
}
Expand Down
Expand Up @@ -3,20 +3,20 @@ package com.twitter.querulous.evaluator
import java.sql.{Connection, ResultSet}
import org.apache.commons.dbcp.{DriverManagerConnectionFactory, PoolableConnectionFactory, PoolingDataSource}
import org.apache.commons.pool.impl.GenericObjectPool
import com.twitter.querulous.connectionpool.{ConnectionPool, ConnectionPoolFactory}
import com.twitter.querulous.database.{Database, DatabaseFactory}
import com.twitter.querulous.query.QueryFactory

class StandardQueryEvaluatorFactory(
connectionPoolFactory: ConnectionPoolFactory,
databaseFactory: DatabaseFactory,
queryFactory: QueryFactory) extends QueryEvaluatorFactory {

def apply(dbhosts: List[String], dbname: String, username: String, password: String) = {
val connectionPool = connectionPoolFactory(dbhosts, dbname, username, password)
new StandardQueryEvaluator(connectionPool, queryFactory)
val database = databaseFactory(dbhosts, dbname, username, password)
new StandardQueryEvaluator(database, queryFactory)
}
}

class StandardQueryEvaluator(protected val connectionPool: ConnectionPool, queryFactory: QueryFactory)
class StandardQueryEvaluator(protected val database: Database, queryFactory: QueryFactory)
extends QueryEvaluator {

def select[A](query: String, params: Any*)(f: ResultSet => A) = withTransaction(_.select(query, params: _*)(f))
Expand Down Expand Up @@ -46,22 +46,22 @@ class StandardQueryEvaluator(protected val connectionPool: ConnectionPool, query
}

def withConnection[A](f: Connection => A): A = {
val connection = connectionPool.reserve()
val connection = database.reserve()
try {
f(connection)
} finally {
connectionPool.release(connection)
database.release(connection)
}
}

override def equals(other: Any) = {
other match {
case other: StandardQueryEvaluator =>
connectionPool eq other.connectionPool
database eq other.database
case _ =>
false
}
}

override def hashCode = connectionPool.hashCode
override def hashCode = database.hashCode
}
Expand Up @@ -3,9 +3,9 @@ package com.twitter.querulous.fake
import java.sql.Connection
import com.twitter.xrayspecs.{Duration, Time}
import com.twitter.xrayspecs.TimeConversions._
import com.twitter.querulous.connectionpool.ConnectionPool
import com.twitter.querulous.database.Database

class FakeConnectionPool(connection: Connection, latency: Duration) extends ConnectionPool {
class FakeDatabase(connection: Connection, latency: Duration) extends Database {
def reserve(): Connection = {
Time.advance(latency)
connection
Expand Down
Expand Up @@ -5,7 +5,7 @@ import org.specs.Specification
import net.lag.configgy.Configgy
import com.twitter.xrayspecs.Time
import com.twitter.xrayspecs.TimeConversions._
import com.twitter.querulous.connectionpool.ApacheConnectionPoolFactory
import com.twitter.querulous.database.ApachePoolingDatabaseFactory
import com.twitter.querulous.query._
import com.twitter.querulous.evaluator.{StandardQueryEvaluatorFactory, QueryEvaluator}

Expand Down
Expand Up @@ -5,7 +5,7 @@ import org.specs.Specification
import net.lag.configgy.Configgy
import com.twitter.xrayspecs.Time
import com.twitter.xrayspecs.TimeConversions._
import com.twitter.querulous.connectionpool.ApacheConnectionPoolFactory
import com.twitter.querulous.database.ApachePoolingDatabaseFactory
import com.twitter.querulous.query.{SqlQueryFactory, TimingOutQueryFactory, SqlTimeoutException}
import com.twitter.querulous.evaluator.{StandardQueryEvaluatorFactory, QueryEvaluator}

Expand All @@ -16,9 +16,9 @@ object TimeoutSpec extends Specification {
val timeout = 1.second
val queryFactory = new SqlQueryFactory
val timingOutQueryFactory = new TimingOutQueryFactory(queryFactory, timeout)
val connectionPoolFactory = new ApacheConnectionPoolFactory(1, 1, 1.second, 20.millis, false, 0.seconds)
val queryEvaluatorFactory = new StandardQueryEvaluatorFactory(connectionPoolFactory, queryFactory)
val timingOutQueryEvaluatorFactory = new StandardQueryEvaluatorFactory(connectionPoolFactory, timingOutQueryFactory)
val databaseFactory = new ApachePoolingDatabaseFactory(1, 1, 1.second, 20.millis, false, 0.seconds)
val queryEvaluatorFactory = new StandardQueryEvaluatorFactory(databaseFactory, queryFactory)
val timingOutQueryEvaluatorFactory = new StandardQueryEvaluatorFactory(databaseFactory, timingOutQueryFactory)

"Timeouts" should {
doBefore {
Expand Down
Expand Up @@ -2,28 +2,28 @@ package com.twitter.querulous.unit

import org.specs.mock.JMocker
import org.specs.Specification
import com.twitter.querulous.connectionpool.{ConnectionPool, ConnectionPoolFactory, MemoizingConnectionPoolFactory}
import com.twitter.querulous.database.{Database, DatabaseFactory, MemoizingDatabaseFactory}

object MemoizingConnectionPoolFactorySpec extends Specification with JMocker {
object MemoizingDatabaseFactorySpec extends Specification with JMocker {
val username = "username"
val password = "password"
val hosts = List("foo")

"MemoizingConnectionPoolFactory" should {
"MemoizingDatabaseFactory" should {
"apply" in {
val connectionPool1 = mock[ConnectionPool]
val connectionPool2 = mock[ConnectionPool]
val connectionPoolFactory = mock[ConnectionPoolFactory]
val memoizingConnectionPool = new MemoizingConnectionPoolFactory(connectionPoolFactory)
val database1 = mock[Database]
val database2 = mock[Database]
val databaseFactory = mock[DatabaseFactory]
val memoizingDatabase = new MemoizingDatabaseFactory(databaseFactory)

expect {
one(connectionPoolFactory).apply(hosts, "bar", username, password) willReturn connectionPool1
one(connectionPoolFactory).apply(hosts, "baz", username, password) willReturn connectionPool2
one(databaseFactory).apply(hosts, "bar", username, password) willReturn database1
one(databaseFactory).apply(hosts, "baz", username, password) willReturn database2
}
memoizingConnectionPool(hosts, "bar", username, password) mustBe connectionPool1
memoizingConnectionPool(hosts, "bar", username, password) mustBe connectionPool1
memoizingConnectionPool(hosts, "baz", username, password) mustBe connectionPool2
memoizingConnectionPool(hosts, "baz", username, password) mustBe connectionPool2
memoizingDatabase(hosts, "bar", username, password) mustBe database1
memoizingDatabase(hosts, "bar", username, password) mustBe database1
memoizingDatabase(hosts, "baz", username, password) mustBe database2
memoizingDatabase(hosts, "baz", username, password) mustBe database2
}
}
}
Expand Up @@ -4,7 +4,7 @@ import java.sql.{Connection, SQLException, DriverManager}
import scala.collection.mutable
import net.lag.configgy.Configgy
import com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException
import com.twitter.querulous.connectionpool.ConnectionPool
import com.twitter.querulous.database.Database
import com.twitter.querulous.evaluator.{StandardQueryEvaluator, QueryEvaluator}
import com.twitter.querulous.query.{QueryFactory, SqlQueryFactory}
import com.twitter.xrayspecs.Time
Expand Down Expand Up @@ -33,16 +33,16 @@ object QueryEvaluatorSpec extends Specification with JMocker {
"connection pooling" in {
"transactionally" >> {
val connection = mock[Connection]
val connectionPool = mock[ConnectionPool]
val queryEvaluator = new StandardQueryEvaluator(connectionPool, queryFactory)
val database = mock[Database]
val queryEvaluator = new StandardQueryEvaluator(database, queryFactory)

expect {
one(connectionPool).reserve() willReturn connection
one(database).reserve() willReturn connection
one(connection).setAutoCommit(false)
one(connection).prepareStatement("SELECT 1")
one(connection).commit()
one(connection).setAutoCommit(true)
one(connectionPool).release(connection)
one(database).release(connection)
}

queryEvaluator.transaction { transaction =>
Expand All @@ -52,13 +52,13 @@ object QueryEvaluatorSpec extends Specification with JMocker {

"nontransactionally" >> {
val connection = mock[Connection]
val connectionPool = mock[ConnectionPool]
val queryEvaluator = new StandardQueryEvaluator(connectionPool, queryFactory)
val database = mock[Database]
val queryEvaluator = new StandardQueryEvaluator(database, queryFactory)

expect {
one(connectionPool).reserve() willReturn connection
one(database).reserve() willReturn connection
one(connection).prepareStatement("SELECT 1")
one(connectionPool).release(connection)
one(database).release(connection)
}

var list = new mutable.ListBuffer[Int]
Expand Down

0 comments on commit 124e98d

Please sign in to comment.