Skip to content

Commit

Permalink
add autodisablingdatabase
Browse files Browse the repository at this point in the history
  • Loading branch information
Ed Ceaser authored and freels committed Sep 7, 2010
1 parent 4b452a0 commit de47bf9
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 23 deletions.
35 changes: 35 additions & 0 deletions src/main/scala/com/twitter/querulous/AutoDisabler.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.twitter.querulous

import com.twitter.xrayspecs.{Time, Duration}
import com.twitter.xrayspecs.TimeConversions._
import java.sql.{SQLException, SQLIntegrityConstraintViolationException}


trait AutoDisabler {
protected val disableErrorCount: Int
protected val disableDuration: Duration

private var disabledUntil: Time = Time.never
private var consecutiveErrors = 0

protected def throwIfDisabled() {
synchronized {
if (Time.now < disabledUntil) {
throw new SQLException("Server is temporarily disabled")
}
}
}

protected def noteOperationOutcome(success: Boolean) {
synchronized {
if (success) {
consecutiveErrors = 0
} else {
consecutiveErrors += 1
if (consecutiveErrors >= disableErrorCount) {
disabledUntil = disableDuration.fromNow
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.twitter.querulous.database

import com.twitter.xrayspecs.Duration
import com.twitter.xrayspecs.TimeConversions._
import java.sql.{Connection, SQLException, SQLIntegrityConstraintViolationException}


class AutoDisablingDatabaseFactory(databaseFactory: DatabaseFactory, disableErrorCount: Int, disableDuration: Duration) extends DatabaseFactory {
def apply(dbhosts: List[String], dbname: String, username: String, password: String) = {
new AutoDisablingDatabase(databaseFactory(dbhosts, dbname, username, password), disableErrorCount, disableDuration)
}

def apply(dbhosts: List[String], username: String, password: String) = {
new AutoDisablingDatabase(databaseFactory(dbhosts, username, password), disableErrorCount, disableDuration)
}
}

class AutoDisablingDatabase(database: Database, protected val disableErrorCount: Int, protected val disableDuration: Duration) extends Database with AutoDisabler {
def open() = {
throwIfDisabled()
try {
val rv = database.open()
noteOperationOutcome(true)
rv
} catch {
case e: SQLException =>
noteOperationOutcome(false)
throw e
case e: Exception =>
throw e
}
}

def close(connection: Connection) { database.close(connection) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ class AutoDisablingQueryEvaluatorFactory(
}
}

class AutoDisablingQueryEvaluator(
class AutoDisablingQueryEvaluator (
queryEvaluator: QueryEvaluator,
disableErrorCount: Int,
disableDuration: Duration) extends QueryEvaluatorProxy(queryEvaluator) {
protected val disableErrorCount: Int,
protected val disableDuration: Duration) extends QueryEvaluatorProxy(queryEvaluator) with AutoDisabler {

private var disabledUntil: Time = Time.never
private var consecutiveErrors = 0
Expand All @@ -56,24 +56,4 @@ class AutoDisablingQueryEvaluator(
}
}

private def noteOperationOutcome(success: Boolean) {
synchronized {
if (success) {
consecutiveErrors = 0
} else {
consecutiveErrors += 1
if (consecutiveErrors >= disableErrorCount) {
disabledUntil = disableDuration.fromNow
}
}
}
}

private def throwIfDisabled() {
synchronized {
if (Time.now < disabledUntil) {
throw new SQLException("Server is temporarily disabled")
}
}
}
}

0 comments on commit de47bf9

Please sign in to comment.