Created
May 10, 2015 20:23
-
-
Save brianwawok/01db9d8a1efcff5d2691 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//EXAMPLE evolution.scala | |
import java.io.{File, FilenameFilter} | |
import com.datastax.driver.core.Session | |
import org.apache.commons.io.filefilter.SuffixFileFilter | |
import org.joda.time.{DateTime, DateTimeZone} | |
import play.api.Play.current | |
import play.api.{Logger, Play} | |
import scala.collection.JavaConversions._ | |
import scala.io.Source | |
trait Evolution{ | |
def evolve(session: Session) | |
} | |
object Evolutions { | |
def migrate(session: Session): Unit = { | |
Logger.info("Starting evolution check...") | |
val initialTable = | |
""" | |
|CREATE TABLE IF NOT EXISTS evolutions( | |
|name text, | |
|applied_date timestamp, | |
|content text, | |
|PRIMARY KEY (name)) | |
""".stripMargin | |
session.execute(initialTable) | |
val appliedSql = "select name from evolutions" | |
val appliedEvolutions = session.execute(appliedSql).all().map(row => { | |
row.getString(0) | |
}).toSet | |
Logger.debug(s"We found a total of ${appliedEvolutions.size} applied evolutions") | |
//first apply cql evolutions | |
val baseDirectory = Play.getExistingFile("conf/evolutions").getOrElse(sys.error("Unable to find file conf/evolutions")) | |
val evolutions = baseDirectory.listFiles(new SuffixFileFilter("cql").asInstanceOf[FilenameFilter]).sorted | |
evolutions.foreach(evolutionFile => { | |
val evolutionName = parseEvolutionName(evolutionFile) | |
if (appliedEvolutions.contains(evolutionName)) { | |
Logger.debug(s"Skipping previously applied evolution $evolutionName") | |
} else { | |
Logger.info(s"Applying new evolution $evolutionName") | |
val content = Source.fromFile(evolutionFile).mkString | |
Source.fromFile(evolutionFile).getLines().filterNot(isComment).mkString("\n").split(";").map(_.trim).foreach(statement => { | |
if (isInvalidStatement(statement)) { | |
Logger.debug(s"Skipping invalid statement $statement") | |
} else if (isExec(statement)){ | |
val className = statement.replaceAll("EXEC", "").trim | |
Logger.debug(s"Executing class $className") | |
val clazz = Class.forName(className) | |
val instance = clazz.newInstance().asInstanceOf[Evolution] | |
instance.evolve(session) | |
} else { | |
Logger.debug(s"Executing valid statement '$statement'") | |
session.execute(statement) | |
Thread.sleep(1000) | |
} | |
}) | |
Logger.debug("Saving applied evolution to database") | |
val appliedDate = DateTime.now(DateTimeZone.UTC).toDate | |
val insertStatement = | |
""" | |
|INSERT INTO evolutions (name, applied_date, content) values (?, ?, ?) | |
""".stripMargin | |
session.execute(insertStatement, evolutionName, appliedDate, content) | |
} | |
}) | |
Logger.info(s"Completed evolution. We are now at version ${parseEvolutionName(evolutions.last)}") | |
} | |
private def isComment(statement: String): Boolean = { | |
statement.startsWith("#") | |
} | |
private def isExec(statement : String) : Boolean = { | |
statement.startsWith("EXEC") | |
} | |
private def isInvalidStatement(line: String): Boolean = { | |
line.length == 0 || isComment(line) | |
} | |
private def parseEvolutionName(file : File) : String = { | |
file.getName.split("\\.").head.toUpperCase | |
} | |
} | |
//example file 2015-05-10.cql to be placed in /conf/evolutions | |
CREATE TABLE foobar ( | |
businessId uuid, | |
createdDate timestamp, | |
PRIMARY KEY(businessId) | |
) | |
AND gc_grace_seconds = 3600; | |
ALTER TABLE zooRaw ADD newColumn boolean; | |
EXEC com.test.Evolution201505051625; | |
//sample file com.test.Evolution201505051625 to be placed in with the normal app and do code type migrations | |
package com.foo.evolutions | |
import com.datastax.driver.core.Session | |
import com.foo.Evolution | |
import scala.collection.JavaConversions._ | |
class Evolution201505051625 extends Evolution { | |
override def evolve(session: Session): Unit = { | |
val emails = session.execute("select distinct email from users").all().map(row => { | |
row.getString(0).trim | |
}) | |
emails.map(email => { | |
session.execute(s"update otherTableBar set last_name = 'Fred' where email = ?", email) | |
}) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ty