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

3 years ago
  1. package wow.doge.http4sdemo.services
  2. import monix.bio.IO
  3. import monix.bio.Task
  4. import slick.jdbc.JdbcBackend
  5. import slick.jdbc.JdbcProfile
  6. import wow.doge.http4sdemo.dto.Book
  7. import wow.doge.http4sdemo.dto.BookUpdate
  8. import wow.doge.http4sdemo.dto.NewBook
  9. import wow.doge.http4sdemo.implicits._
  10. import wow.doge.http4sdemo.slickcodegen.Tables
  11. class LibraryService(
  12. profile: JdbcProfile,
  13. dbio: LibraryDbio,
  14. db: JdbcBackend.DatabaseDef
  15. ) {
  16. import profile.api._
  17. def getBooks = db.streamO(dbio.getBooks)
  18. def getBookById(id: Int) = db.runL(dbio.getBook(id))
  19. // .map(b =>
  20. // (b.title, b.authorId, b.createdAt).mapTo[BookUpdateEntity]
  21. // )
  22. def updateBook(id: Int, updateData: BookUpdate) =
  23. for {
  24. action <- IO.deferAction { implicit s =>
  25. Task(for {
  26. mbRow <- dbio.selectBook(id).result.headOption
  27. updatedRow <- mbRow match {
  28. case Some(value) =>
  29. println(s"Original value -> $value")
  30. println(s"Value to be updated with -> $updateData")
  31. DBIO.successful(updateData.update(value))
  32. case None =>
  33. DBIO.failed(new Exception(s"Book with id $id does not exist"))
  34. }
  35. updateAction = dbio.selectBook(id).update(updatedRow)
  36. _ = println(s"SQL = ${updateAction.statements}")
  37. _ <- updateAction
  38. } yield ())
  39. }
  40. _ <- db.runL(action.transactionally.asTry).flatMap(Task.fromTry)
  41. } yield ()
  42. def deleteBook(id: Int) = db.runL(dbio.deleteBook(id))
  43. def insertBook(newBook: NewBook) =
  44. Task.deferFutureAction { implicit s =>
  45. val action = for {
  46. id <- dbio.insertBookAndGetId(newBook)
  47. book <- dbio.getBook(id)
  48. } yield book.get
  49. db.run(action.transactionally)
  50. }
  51. def booksForAuthor(authorId: Int) =
  52. db.streamO(dbio.booksForAuthor(authorId)).map(Book.fromBooksRow)
  53. }
  54. class LibraryDbio(val profile: JdbcProfile) {
  55. import profile.api._
  56. def getBooks: StreamingDBIO[Seq[Book], Book] = Query.getBooksInner.result
  57. def insertBookAndGetId(newBook: NewBook): DBIO[Int] =
  58. Query.insertBookGetId += newBook
  59. def insertBookAndGetBook(newBook: NewBook): DBIO[Book] =
  60. Query.insertBookGetBook += newBook
  61. def selectBook(id: Int) = Tables.Books.filter(_.id === id)
  62. def deleteBook(id: Int) = selectBook(id).delete
  63. def getBook(id: Int) = selectBook(id)
  64. .map(Book.fromBooksTableFn)
  65. .result
  66. .headOption
  67. def booksForAuthor(authorId: Int) = Query.booksForAuthorInner(authorId).result
  68. private object Query {
  69. val getBooksInner = Book.fromBooksTable
  70. val insertBookGetId =
  71. NewBook.fromBooksTable.returning(Tables.Books.map(_.id))
  72. val insertBookGetBook = NewBook.fromBooksTable.returning(getBooksInner)
  73. def booksForAuthorInner(authorId: Int) = for {
  74. b <- Tables.Books
  75. a <- selectAuthor(authorId) if b.authorId === a.id
  76. } yield b
  77. def selectAuthor(authorId: Int) = Tables.Authors.filter(_.id === authorId)
  78. }
  79. }