You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.9 KiB

package wow.doge.http4sdemo.services
import monix.bio.IO
import monix.bio.Task
import slick.jdbc.JdbcBackend
import slick.jdbc.JdbcProfile
import wow.doge.http4sdemo.dto.Book
import wow.doge.http4sdemo.dto.BookUpdate
import wow.doge.http4sdemo.dto.NewBook
import wow.doge.http4sdemo.implicits._
import wow.doge.http4sdemo.slickcodegen.Tables
class LibraryService(
profile: JdbcProfile,
dbio: LibraryDbio,
db: JdbcBackend.DatabaseDef
) {
import profile.api._
def getBooks = db.streamO(dbio.getBooks)
def getBookById(id: Int) = db.runL(dbio.getBook(id))
// .map(b =>
// (b.title, b.authorId, b.createdAt).mapTo[BookUpdateEntity]
// )
def updateBook(id: Int, updateData: BookUpdate) =
for {
action <- IO.deferAction { implicit s =>
Task(for {
mbRow <- dbio.selectBook(id).result.headOption
updatedRow <- mbRow match {
case Some(value) =>
println(s"Original value -> $value")
println(s"Value to be updated with -> $updateData")
DBIO.successful(updateData.update(value))
case None =>
DBIO.failed(new Exception(s"Book with id $id does not exist"))
}
updateAction = dbio.selectBook(id).update(updatedRow)
_ = println(s"SQL = ${updateAction.statements}")
_ <- updateAction
} yield ())
}
_ <- db.runL(action.transactionally.asTry).flatMap(Task.fromTry)
} yield ()
def deleteBook(id: Int) = db.runL(dbio.deleteBook(id))
def insertBook(newBook: NewBook) =
Task.deferFutureAction { implicit s =>
val action = for {
id <- dbio.insertBookAndGetId(newBook)
book <- dbio.getBook(id)
} yield book.get
db.run(action.transactionally)
}
def booksForAuthor(authorId: Int) =
db.streamO(dbio.booksForAuthor(authorId)).map(Book.fromBooksRow)
}
class LibraryDbio(val profile: JdbcProfile) {
import profile.api._
def getBooks: StreamingDBIO[Seq[Book], Book] = Query.getBooksInner.result
def insertBookAndGetId(newBook: NewBook): DBIO[Int] =
Query.insertBookGetId += newBook
def insertBookAndGetBook(newBook: NewBook): DBIO[Book] =
Query.insertBookGetBook += newBook
def selectBook(id: Int) = Tables.Books.filter(_.id === id)
def deleteBook(id: Int) = selectBook(id).delete
def getBook(id: Int) = selectBook(id)
.map(Book.fromBooksTableFn)
.result
.headOption
def booksForAuthor(authorId: Int) = Query.booksForAuthorInner(authorId).result
private object Query {
val getBooksInner = Book.fromBooksTable
val insertBookGetId =
NewBook.fromBooksTable.returning(Tables.Books.map(_.id))
val insertBookGetBook = NewBook.fromBooksTable.returning(getBooksInner)
def booksForAuthorInner(authorId: Int) = for {
b <- Tables.Books
a <- selectAuthor(authorId) if b.authorId === a.id
} yield b
def selectAuthor(authorId: Int) = Tables.Authors.filter(_.id === authorId)
}
}