(ECS) ▸ Servers are properly decoupled by docker containers Client AUTH CS ETC.. PUBLIC API ADMIN Docker Containers Data HTTPS MySQL Elasticache S3 αʔό%PDLFSίϯςφʹΑׂͬͯɾૄ݁߹Խ
architecture ▸ Value object is defined as "object" ▸ Entity is defined as "case class" ▸ Separate layers with "protected" PRESENTATION DOMAIN DATA ACCESS Layered architecture ཧ༝ͷҰͭ%%%ͱੑ͕ߴ͍͜ͱ
errors in functional way ▸ Either \/ monad in Scalaz ▸ ScalazΛ͓͏ #1 – NET BIZ DIV. TECH BLOG http://tech.recruit-mp.co.jp/server-side/post-2540/ ϞφυؔܕͷಛΛ׆༻ͯ͠มߋʹڧ͍ίʔυΛॻ͘
know in what environment server is running for devs ▸ Platform ▸ JDK version ▸ Timezone AUTH CS ETC.. PUBLIC API ADMIN Production Environment DOCKER IMAGE Run containers %PDLFSʹΑͬͯ։ൃऀ͕ຊ൪ڥͷ༷ࢠΛѲ͘͢͠ͳΔ
debug ▸ Use MySQL container in local ▸ If It's needed (for migration test etc…) Docker Container in docker-machine (Virtualbox) H2 Database Unit test (In-memory DB) Switch if needed ։ൃʹJOUFMMJ+Λར༻ɺ%#ඞཁʹԠͯ͡Γସ͑
(in-memory DB) ▸ Jenkins CI ▸ Run unit tests ▸ with using MySQL Devs Develop + Write Test Run tests each commits git push webhook +FOLJOT্Ͱͷςετ࣮ߦ.Z42-ͱଓ
use sbt clean if it's not needed ▸ Use incremental compile function if possible Clean & Test Test Test Test Clean & Test develop feature-A ίϯύΠϧ͘ͳΔͷͰ$MFBOඞཁͳ࣌ʹ͔͠͠ͳ͍
registry Push docker image ECS Upgrade services via ECS API pull AUTH CS ETC.. PUBLIC API ADMIN Production Environment Switch server's role by application.conf ԿͷαʔόΛσϓϩΠ͢Δ͔DPOGϑΝΠϧͰࢦఆ
{ http { router = route.api.Routes } } prod_api.conf ECS AUTH CS ETC.. PUBLIC API ADMIN Production Environment Switch server's role by application.conf DPOGϑΝΠϧͰΤϯυϙΠϯτͷΓସ͑ߦ͏
file ./sbt clean assembly ▸ Execute jar Executes play application by one shot java -Dconfig.resource=batch.conf -cp ./target/scala-2.11/app-x.x.jar tasks.SomeTask ίϯύΠϧࡁΈKBSΛεέδϡʔϧ࣮ߦ͢Δ
one shot java -Dconfig.resource=batch.conf -cp ./target/scala-2.11/app-x.x.jar tasks.SomeTask package tasks import com.typesafe.scalalogging.LazyLogging object SomeTask extends App with Task with LazyLogging { withApplication( app => { doSomething() // Do something }, ex => ex match { case ex => logger.error(ex.getMessage, ex) println("Something went wrong") } ) } ͍ͤͨ͞όονॲཧΛίϚϯυҾͰࢦఆ
▸ Enable useLocks option if you have Play nodes that may potential run evolutions ▸ Evolutions https://www.playframework.com/documentation/2.4.x/Evolutions VTF-PDLTͰෳσϓϩΠ࣌ͷFWPMVUJPOͷൃΛࢭΊΔ
Evolution should be executed carefully ▸ Execute evolutions safely before deployments with one-shot style as a Jenkins job java -Dconfig.resource=batch.conf -Dplay.evolutions.db.default.autoApply=true -Dplay.mode=prod -cp ./target/scala-2.11/app-x.x.jar tasks.EvolutionsCheckTask One-shot evolution example FWPMVUJPOσϓϩΠͷલʹ୯ମͰ࣮ߦ͓ͯ͘͠ͷ͕҆৺
Evolution should be executed carefully ▸ Execute evolutions safely before deployments with one-shot style as a Jenkins job java -Dconfig.resource=batch.conf -Dplay.evolutions.db.default.autoApply=true -Dplay.mode=prod -cp ./target/scala-2.11/app-x.x.jar tasks.EvolutionsCheckTask One-shot evolution example package tasks import com.typesafe.scalalogging.LazyLogging object EvolutionsCheckTask extends App with Task with LazyLogging { withApplication( app => { logger.info("unnecessary") }, ex => ex match { case ex: play.api.db.evolutions.InvalidDatabaseRevision => logger.warn("necessary") case ex => logger.error(ex.getMessage, ex) println("Error") } ) } tasks.EvolutionsCheckTask
Ͱ PlayʢScalaʣ ͷόονॲཧΛ࣮ߦ͢Δ http://tech.recruit-mp.co.jp/server-side/post-5473/ ▸ ScalazΛ͓͏ #1 – NET BIZ DIV. TECH BLOG http://tech.recruit-mp.co.jp/server-side/post-2540/