I would like to implement an evolution that applies only if a condition is met on a Scala Play framework application. The condition is that the application should be in a certain environment.
I have this evolution right now:
# payments SCHEMA # --- !Ups INSERT INTO table1 (id, provider_name, provider_country, provider_code, status, flag) VALUES (10, 'XXXXX', 'XX', 'XXXXX', '1', '0'); # --- !Downs DELETE FROM table2 WHERE id = 10;
I want the evolution to run if this condition is met
if(config.env == 'dev'){ //execute evolution }
How do I achieve this? Is this a function of the evolution or the application logic?
3 Answers
Answers 1
Ideally production code should not be polluted with DEV artefacts, so I believe this is a function of evolutions.
Say we have production evolutions under
conf/evolutions/default
We could create corresponding DEV evolutions under
conf/evolutions/dev
Then we could load the appropriate DB on the basis of an env flag:
class SomeRepository @Inject()(dbapi: DBApi, config: Configuration)(implicit ec: DatabaseExecutionContext) { private val db = if(config.env == "dev"){ dbapi.database("dev") } else { dbapi.database("default") } def findById(id: Long): Future[Option[SomeModel]] = Future { db.withConnection { implicit connection => SQL"select * from ... } }(ec) ... }
Answers 2
One approach might be to use a stored procedure in conjunction with a db-based app 'setting'. Assume your app had an appSetting table for storing app settings.
create table appSetting ( name varchar(63) not null primary key, value varchar(255) ) ; -- insert into appSetting values ('environment','dev');
Then, something along the following lines would create a tmpLog table (or insert a value into table1) only if appSetting has a value of 'dev' for setting 'environment' at the time of running the evolution:
# --- !Ups create procedure doEvolution31() begin declare environment varchar(31);; select value into environment from appSetting where name='environment' ;; if (environment='dev') then create table tmpLog (id int not null primary key, text varchar(255));; -- or INSERT INTO table1 (id, provider_name, provider_country, provider_code, status, flag) VALUES (10, 'XXXXX', 'XX', 'XXXXX', '1', '0'); end if;; end ; call doEvolution31(); # --- !Downs drop procedure doEvolution31; drop table if exists tmpLog; -- or delete from table2 where id=10;
You don't mention which db you are using. The above is MYSQL syntax. There might be a way to get a config value into the stored proc, perhaps via some sbt magic, but I think we would use the above if we had such a requirement. (BTW The double semicolons are for escaping out a single semicolon so that individual statements of the procedures are not executed when the procedure is being created.)
Answers 3
Why do you need it at all? Don't you use separate db for different environments as it's being told at documentation? If you do - then you probably have different db configurations, probably at different files. That, probably, looks something like that:
# application.conf db.default { driver=com.mysql.jdbc.Driver url="jdbc:mysql://localhost/playdb" username=playdbuser password="a strong password" } # dev.conf db.dev { driver=com.mysql.jdbc.Driver url="jdbc:mysql://localhost/playdb" username=playdbuser password="a strong password" } # staging.conf db.staging { driver=com.mysql.jdbc.Driver url="jdbc:mysql://localhost/playdb" username=playdbuser password="a strong password" } # prod.conf db.prod { driver=com.mysql.jdbc.Driver url="jdbc:mysql://localhost/playdb" username=playdbuser password="a strong password" }
Actually nothing stops you to make it the same db but don't - just use proper db per environment. Assuming you are using jdbc connector and PlayEvolutions plugin - just put your evolution to right directory and you'll achieve what you want. The other question is actually: "How to use proper db per environment?" And the answer is strongly depend on your choice of DI.
0 comments:
Post a Comment