SlideShare une entreprise Scribd logo
1  sur  14
Télécharger pour lire hors ligne
Eishay Smith (CTO & Founder)
@eishay of @42eng
on @
42go.com
Agenda
• Intro to Slick
• How we use it at FortyTwo
• Wrapping Sessions
• Generic Access Layer
About Slick
Database query library for Scala
"select * from users where id=?"
or
def get(id: Long): User =
(for(u <- UserTable if u.id is id) yield u).first
or
def get(id: Id[M]): M =
(for(f <- table if f.id is id) yield f).first
Can do: insert, update, delete, DDL and more
More About Slick
• Using Options to represent NULLs
• Creates DDLs (tests without Play)
• Type safe in and out
• Syntax safe
• Custom types
• Can use regular sql
• With type safe wrapping
Type Safe Concurrency
abstract class RSession(roSession: => Session) extends SessionWrapper(roSession)
class ROSession(roSession: => Session) extends RSession(roSession)
class RWSession(rwSession: Session) extends RSession(rwSession)
class Database @Inject() (val db: DataBaseComponent) {
  import DBSession._
 
private def rawSession = db.handle.createSession()
 
def readOnly[T](f: ROSession => T): T = {
val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.ReadOnly)
try f(new ROSession(s)) finally s.close()
}
 
def readWrite[T](f: RWSession => T): T = {
val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.Updatable))
try {
rw.withTransaction { f(new RWSession(s)) }
} finally s.close()
}
}
Using Sessions
db.readOnly { implicit s =>
// only reading from db - not in a transaction
val users = userRepo.getUsersByLastName(“Smith”)
accountRepo.getAccounts(users)
}
db.readWrite { implicit s =>
// reading and writing to db in a transaction
val users = userRepo.getUsersByLastName(“Smith”)
accountRepo.deleteAccounts(users)
userRepo.markUsersAsInactive(users)
}
db.readOnly { implicit s =>
val user = userRepo.get(userId)
emailRepo.updateEmail(user, newMail) <-- FAIL
}
DB Repo
trait Repo[M <: Model[M]] {
def get(id: Id[M])(implicit session: RSession): M
def all()(implicit session: RSession): Seq[M]
def save(model: M)(implicit session: RWSession): M
def count(implicit session: RSession): Int.
def page(page: Int = 0, size: Int = 20)
(implicit session: RSession): Seq[M]
}
DB Repo Impl
trait DbRepo[M <: Model[M]] extends Repo[M] {
protected def table: RepoTable[M]
 
//you don’t have to run the whole Play Application to get the db setup!
def descTable(): String = db.handle.withSession {
table.ddl.createStatements mkString "n"
}
 
def count(implicit session: RSession): Int = Query(table.length).first
 
def get(id: Id[M])(implicit session: RSession): M =
(for(f <- table if f.id is id) yield f).first
 
def all()(implicit session: RSession): Seq[M] = table.map(t => t).list
def page(page: Int = 0, size: Int = 20)(implicit session: RSession): Seq[M] = {
val q = for {
t <- table
} yield t
q.sortBy(_.id desc).drop(page * size).take(size).list
}
}
DB Repo Impl - Persisting
def save(model: M)(implicit session: RWSession): M = try {
val toUpdate = model.withUpdateTime(clock.now)
val result = model.id match {
case Some(id) => update(toUpdate)
case None => toUpdate.withId(insert(toUpdate))
}
} catch {
case t: SQLException => throw new SQLException(s"error persisting $model", t)
}
private def insert(model: M)(implicit session: RWSession) =
table.autoInc.insert(model)
 
private def update(model: M)(implicit session: RWSession) = {
val target = for(t <- table if t.id === model.id.get) yield t
val count = target.update(model)
assert(1 == count)
model
}
RepoTable
abstract class RepoTable[M <: Model[M]]
(db: DataBaseComponent, name: String) extends Table[M]
(db.entityName(name)) with TableWithDDL {
//standardizing the following columns for all entities
def id = column[Id[M]]("ID", O.PrimaryKey, O.Nullable, O.AutoInc)
def createdAt = column[DateTime]("created_at", O.NotNull)
def updatedAt = column[DateTime]("updated_at", O.NotNull)
def autoInc = * returning id
 
//H2 likes its column names in upper case where mysql does not mind.
//the db component should figure it out
override def column[C : TypeMapper](name: String, options: ColumnOption[C]*) =
super.column(db.entityName(name), options:_*)
}
}
Example - User
case class User(
id: Option[Id[User]] = None,
createdAt: DateTime,
updatedAt: DateTime,
firstName: String,
lastName: String
) extends Model[User] {
def withName(firstName: String, lastName: String) =
copy(firstName = firstName, lastName = lastName)
}
Example - UserRepo
@ImplementedBy(classOf[UserRepoImpl])
trait UserRepo extends Repo[User] {
def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User]
}
@Singleton
class UserRepoImpl @Inject() (val db: DataBaseComponent, val clock: Clock)
extends DbRepo[User] with UserRepo {
 
override val table = new RepoTable[User](db, "user") {
def firstName = column[String]("first_name", O.NotNull)
def lastName = column[String]("last_name", O.NotNull)
def * = id.? ~ createdAt ~ updatedAt ~ firstName ~ lastName <>
(User.apply _, User.unapply _)
}
 
def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User] =
(for (u <- table if u.lastName = lastName yield u).list
}
Q & A
Binding (with Guice)
trait DbInfo {
def database: SlickDatabase
def driverName: String
}
 
class SlickModule(dbInfo: DbInfo) extends ScalaModule {
def configure(): Unit = {
lazy val db = dbInfo.driverName match {
case MySQL.driverName => new MySQL(dbInfo.database)
case H2.driverName => new H2(dbInfo.database)
}
bind[DataBaseComponent].toInstance(db)
bind[Database].in(classOf[Singleton])
}
}

Contenu connexe

Tendances

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)croquiscom
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional ProgrammingDmitry Buzdin
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Datagreenwop
 
Cycle.js: Functional and Reactive
Cycle.js: Functional and ReactiveCycle.js: Functional and Reactive
Cycle.js: Functional and ReactiveEugene Zharkov
 
Database API, your new friend
Database API, your new friendDatabase API, your new friend
Database API, your new friendkikoalonsob
 
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum Ukraine
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to PythonUC San Diego
 
A Tour to MySQL Commands
A Tour to MySQL CommandsA Tour to MySQL Commands
A Tour to MySQL CommandsHikmat Dhamee
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad Fabernovel
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFabio Collini
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수용 최
 
GreenDao Introduction
GreenDao IntroductionGreenDao Introduction
GreenDao IntroductionBooch Lin
 
Swift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationSwift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationJacopo Mangiavacchi
 

Tendances (19)

JDBC
JDBCJDBC
JDBC
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Sparklyr
SparklyrSparklyr
Sparklyr
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional Programming
 
Enter The Matrix
Enter The MatrixEnter The Matrix
Enter The Matrix
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Data
 
Cycle.js: Functional and Reactive
Cycle.js: Functional and ReactiveCycle.js: Functional and Reactive
Cycle.js: Functional and Reactive
 
Database API, your new friend
Database API, your new friendDatabase API, your new friend
Database API, your new friend
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
 
JDBC Core Concept
JDBC Core ConceptJDBC Core Concept
JDBC Core Concept
 
A Tour to MySQL Commands
A Tour to MySQL CommandsA Tour to MySQL Commands
A Tour to MySQL Commands
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
 
GreenDao Introduction
GreenDao IntroductionGreenDao Introduction
GreenDao Introduction
 
Swift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationSwift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML Personalization
 

Similaire à Using Scala Slick at FortyTwo

Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsEleanor McHugh
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialjbellis
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersKazuhiro Sera
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRick Copeland
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemyInada Naoki
 
Creating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonCreating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonSiddhi
 
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...Michael Rys
 
Database queries
Database queriesDatabase queries
Database querieslaiba29012
 
Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013Samir Bessalah
 
Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02Lalit009kumar
 
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...MongoDB
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveJeff Smith
 
Deep learning study 3
Deep learning study 3Deep learning study 3
Deep learning study 3San Kim
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your CodeDrupalDay
 

Similaire à Using Scala Slick at FortyTwo (20)

Slickdemo
SlickdemoSlickdemo
Slickdemo
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorial
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for Beginners
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
 
Introduction to Quill
Introduction to QuillIntroduction to Quill
Introduction to Quill
 
Creating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonCreating Domain Specific Languages in Python
Creating Domain Specific Languages in Python
 
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
 
Database queries
Database queriesDatabase queries
Database queries
 
Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013
 
Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02
 
DataMapper
DataMapperDataMapper
DataMapper
 
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
 
Lobos Introduction
Lobos IntroductionLobos Introduction
Lobos Introduction
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Code Generation
Code GenerationCode Generation
Code Generation
 
Deep learning study 3
Deep learning study 3Deep learning study 3
Deep learning study 3
 
Sequel
SequelSequel
Sequel
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 

Dernier

Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 

Dernier (20)

Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 

Using Scala Slick at FortyTwo

  • 1. Eishay Smith (CTO & Founder) @eishay of @42eng on @ 42go.com
  • 2. Agenda • Intro to Slick • How we use it at FortyTwo • Wrapping Sessions • Generic Access Layer
  • 3. About Slick Database query library for Scala "select * from users where id=?" or def get(id: Long): User = (for(u <- UserTable if u.id is id) yield u).first or def get(id: Id[M]): M = (for(f <- table if f.id is id) yield f).first Can do: insert, update, delete, DDL and more
  • 4. More About Slick • Using Options to represent NULLs • Creates DDLs (tests without Play) • Type safe in and out • Syntax safe • Custom types • Can use regular sql • With type safe wrapping
  • 5. Type Safe Concurrency abstract class RSession(roSession: => Session) extends SessionWrapper(roSession) class ROSession(roSession: => Session) extends RSession(roSession) class RWSession(rwSession: Session) extends RSession(rwSession) class Database @Inject() (val db: DataBaseComponent) {   import DBSession._   private def rawSession = db.handle.createSession()   def readOnly[T](f: ROSession => T): T = { val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.ReadOnly) try f(new ROSession(s)) finally s.close() }   def readWrite[T](f: RWSession => T): T = { val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.Updatable)) try { rw.withTransaction { f(new RWSession(s)) } } finally s.close() } }
  • 6. Using Sessions db.readOnly { implicit s => // only reading from db - not in a transaction val users = userRepo.getUsersByLastName(“Smith”) accountRepo.getAccounts(users) } db.readWrite { implicit s => // reading and writing to db in a transaction val users = userRepo.getUsersByLastName(“Smith”) accountRepo.deleteAccounts(users) userRepo.markUsersAsInactive(users) } db.readOnly { implicit s => val user = userRepo.get(userId) emailRepo.updateEmail(user, newMail) <-- FAIL }
  • 7. DB Repo trait Repo[M <: Model[M]] { def get(id: Id[M])(implicit session: RSession): M def all()(implicit session: RSession): Seq[M] def save(model: M)(implicit session: RWSession): M def count(implicit session: RSession): Int. def page(page: Int = 0, size: Int = 20) (implicit session: RSession): Seq[M] }
  • 8. DB Repo Impl trait DbRepo[M <: Model[M]] extends Repo[M] { protected def table: RepoTable[M]   //you don’t have to run the whole Play Application to get the db setup! def descTable(): String = db.handle.withSession { table.ddl.createStatements mkString "n" }   def count(implicit session: RSession): Int = Query(table.length).first   def get(id: Id[M])(implicit session: RSession): M = (for(f <- table if f.id is id) yield f).first   def all()(implicit session: RSession): Seq[M] = table.map(t => t).list def page(page: Int = 0, size: Int = 20)(implicit session: RSession): Seq[M] = { val q = for { t <- table } yield t q.sortBy(_.id desc).drop(page * size).take(size).list } }
  • 9. DB Repo Impl - Persisting def save(model: M)(implicit session: RWSession): M = try { val toUpdate = model.withUpdateTime(clock.now) val result = model.id match { case Some(id) => update(toUpdate) case None => toUpdate.withId(insert(toUpdate)) } } catch { case t: SQLException => throw new SQLException(s"error persisting $model", t) } private def insert(model: M)(implicit session: RWSession) = table.autoInc.insert(model)   private def update(model: M)(implicit session: RWSession) = { val target = for(t <- table if t.id === model.id.get) yield t val count = target.update(model) assert(1 == count) model }
  • 10. RepoTable abstract class RepoTable[M <: Model[M]] (db: DataBaseComponent, name: String) extends Table[M] (db.entityName(name)) with TableWithDDL { //standardizing the following columns for all entities def id = column[Id[M]]("ID", O.PrimaryKey, O.Nullable, O.AutoInc) def createdAt = column[DateTime]("created_at", O.NotNull) def updatedAt = column[DateTime]("updated_at", O.NotNull) def autoInc = * returning id   //H2 likes its column names in upper case where mysql does not mind. //the db component should figure it out override def column[C : TypeMapper](name: String, options: ColumnOption[C]*) = super.column(db.entityName(name), options:_*) } }
  • 11. Example - User case class User( id: Option[Id[User]] = None, createdAt: DateTime, updatedAt: DateTime, firstName: String, lastName: String ) extends Model[User] { def withName(firstName: String, lastName: String) = copy(firstName = firstName, lastName = lastName) }
  • 12. Example - UserRepo @ImplementedBy(classOf[UserRepoImpl]) trait UserRepo extends Repo[User] { def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User] } @Singleton class UserRepoImpl @Inject() (val db: DataBaseComponent, val clock: Clock) extends DbRepo[User] with UserRepo {   override val table = new RepoTable[User](db, "user") { def firstName = column[String]("first_name", O.NotNull) def lastName = column[String]("last_name", O.NotNull) def * = id.? ~ createdAt ~ updatedAt ~ firstName ~ lastName <> (User.apply _, User.unapply _) }   def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User] = (for (u <- table if u.lastName = lastName yield u).list }
  • 13. Q & A
  • 14. Binding (with Guice) trait DbInfo { def database: SlickDatabase def driverName: String }   class SlickModule(dbInfo: DbInfo) extends ScalaModule { def configure(): Unit = { lazy val db = dbInfo.driverName match { case MySQL.driverName => new MySQL(dbInfo.database) case H2.driverName => new H2(dbInfo.database) } bind[DataBaseComponent].toInstance(db) bind[Database].in(classOf[Singleton]) } }