No Description

AkkaStreamFileProcessingImpl.scala 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. package fr.natan.akkastreamfileprocessingapi.service
  2. import akka.Done
  3. import akka.actor.ActorSystem
  4. import akka.stream.scaladsl.{Sink, Source}
  5. import com.typesafe.scalalogging.slf4j.Logger
  6. import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.{nameBasics, titleBasics, titlePrincipalsBasics}
  7. import fr.natan.akkastreamfileprocessingapi.models.Models.{Person, TvSerie}
  8. import fr.natan.akkastreamfileprocessingapi.models.ModelsBuilder.buildPersonModel
  9. import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{buildAllPersonsSink, buildAllTvSeriesSink, buildAndValidateSource, buildPersonFlow, buildSource, buildTvSerieFlow, filterPersonByIdFlow, filterPersonByNameFlow, filterTvSerieByIdFlow, filterTvSerieByPrimaryTitleFlow}
  10. import org.slf4j.LoggerFactory
  11. import org.springframework.stereotype.Component
  12. import scala.concurrent.ExecutionContext.Implicits.global
  13. import scala.concurrent.duration.DurationInt
  14. import scala.concurrent.{Await, Future}
  15. import scala.language.postfixOps
  16. import scala.util.{Failure, Success}
  17. //noinspection SpellCheckingInspection
  18. @Component
  19. class AkkaStreamFileProcessingImpl extends AkkaStreamFileProcessing {
  20. implicit val actorSystem: ActorSystem = ActorSystem("AkkaStreamActor")
  21. implicit val logger: Logger = Logger(LoggerFactory.getLogger(this.getClass))
  22. override def getPersonById(personID: String): Future[Person] = {
  23. val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  24. val res: Future[Person] = source
  25. .via(flow = filterPersonByIdFlow(personID = personID))
  26. .runWith(Sink.head)
  27. res.onComplete({
  28. case Failure(exception) => logger.info(s"$exception")
  29. case Success(value:Person) => logger.info(s"$value")
  30. })
  31. res
  32. }
  33. override def getPersonByName(primaryName: String): Future[Person] = {
  34. val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  35. val persons: Future[Person] = source
  36. .via(flow = filterPersonByNameFlow(primaryName = primaryName))
  37. .runWith(Sink.head)
  38. persons.onComplete({
  39. case Failure(exception) => logger.error(s"$exception")
  40. case Success(value: Person) => logger.info(s"$value")
  41. logger.info("SUCCESS")
  42. })
  43. persons
  44. }
  45. override def getTvSerieById(tvSerieID: String): Future[TvSerie] = {
  46. val source: Source[Map[String, String], _] = buildSource(inputFile = titleBasics)
  47. val res: Future[TvSerie] = source
  48. .via(flow = filterTvSerieByIdFlow(tvSerieID = tvSerieID))
  49. .runWith(Sink.head)
  50. res.onComplete({
  51. case Failure(exception) => logger.info(s"$exception")
  52. case Success(value: TvSerie) => logger.info(s"$value")
  53. })
  54. res
  55. }
  56. override def getTvSerieByPrimaryTitle(tvSeriePrimaryTitle: String): List[TvSerie] = {
  57. val tvSeriesSource: Source[Map[String, String], _] = buildAndValidateSource(inputFile = titleBasics)
  58. val tvSries: Future[List[TvSerie]] = tvSeriesSource
  59. .via(flow = filterTvSerieByPrimaryTitleFlow(tvSeriePrimaryTitle = tvSeriePrimaryTitle))
  60. .runWith(Sink.collection)
  61. tvSries.onComplete({
  62. case Failure(exception) => logger.info(s"$exception")
  63. case Success(value: List[TvSerie]) =>
  64. value.foreach((tvSrie: TvSerie) => logger.info(s"$tvSrie"))
  65. logger.info("SUCCESS")
  66. })
  67. Await.result(tvSries,2 minutes)
  68. val tvSriesList : List[TvSerie] = tvSries.value.get.get
  69. tvSriesList
  70. }
  71. private def getTvSerieIdByPrimaryTitle(primaryTitle: String): Future[Option[String]] = {
  72. val source: Source[Map[String, String], _] = buildSource(inputFile = titleBasics)
  73. val res: Future[Option[String]] = source
  74. .filter((rowMap: Map[String, String]) => {
  75. rowMap.getOrElse(key = "primaryTitle", "") == primaryTitle
  76. })
  77. .map((rowMap: Map[String, String]) => rowMap.get("tconst"))
  78. .runWith(Sink.head)
  79. res
  80. }
  81. private def getListOfPersonsIDByTvSerieID(tvSerieIdFuture: Future[Option[String]]): Future[IndexedSeq[Option[String]]] = {
  82. val source: Source[Map[String, String], _] = buildSource(inputFile = titlePrincipalsBasics)
  83. val res: Future[IndexedSeq[Option[String]]] = source
  84. .filter((rowMaps: Map[String, String]) => {
  85. rowMaps.getOrElse(key = "tconst", default = "") == tvSerieIdFuture.value.get.get.get
  86. })
  87. .map((rowMap: Map[String, String]) => {
  88. rowMap.get(key = "nconst")
  89. })
  90. .runWith(Sink.collection)
  91. res
  92. }
  93. private def getListOfPersonsForTvSerie(listPersonsIDsFuture: Future[IndexedSeq[Option[String]]]):
  94. Future[IndexedSeq[Person]] = {
  95. val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  96. val res: Future[IndexedSeq[Person]] = source
  97. .filter((rowMaps: Map[String, String]) => {
  98. listPersonsIDsFuture.value.get.get.contains(rowMaps.get(key = "nconst"))
  99. })
  100. .map((rowMap: Map[String, String]) => {
  101. buildPersonModel(rowMap)
  102. })
  103. .runWith(Sink.collection)
  104. res
  105. }
  106. override def getTeamOfPersonsForTvSerie(tvSeriePrimaryTitle: String): Future[IndexedSeq[Person]] = {
  107. //futures chaining
  108. logger.info("STEP 1/3 START")
  109. val tvSerieIDFuture: Future[Option[String]] = getTvSerieIdByPrimaryTitle(primaryTitle = tvSeriePrimaryTitle)
  110. val finalFuture: Future[IndexedSeq[Person]] =
  111. tvSerieIDFuture.andThen({
  112. case Failure(exception) => logger.error(s"$exception")
  113. case Success(value: Option[String]) =>
  114. logger.info(s"TvSerie ID: $value")
  115. logger.info("STEP 1/3 END")
  116. })
  117. .flatMap({
  118. _ =>
  119. logger.info("STEP 2/3 START")
  120. val listPersonIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(tvSerieIdFuture = tvSerieIDFuture)
  121. listPersonIDsFuture.andThen({
  122. case Failure(exception) => logger.error(s"$exception")
  123. case Success(value) =>
  124. value.foreach((personID: Option[String]) => logger.info(s"Person ID:$personID"))
  125. logger.info("STEP 2/3 END")
  126. })
  127. .flatMap({
  128. future =>
  129. logger.info("STEP 3/3 START")
  130. val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(listPersonsIDsFuture = listPersonIDsFuture)
  131. personsTeamFuture.andThen({
  132. case Failure(exception) => logger.error(s"$exception")
  133. case Success(value: IndexedSeq[Person]) =>
  134. value.foreach((person: Person) => logger.info(s"${person.toString}"))
  135. logger.info("STEP 3/3 END")
  136. })
  137. })
  138. })
  139. finalFuture
  140. }
  141. override def getAllPersons(): Unit = {
  142. val personSource: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  143. //graph
  144. val startTime: Long = System.currentTimeMillis()
  145. val result: Future[Done] = personSource
  146. .via(flow = buildPersonFlow())
  147. .runWith(sink = buildAllPersonsSink(logger = logger))
  148. result.onComplete {
  149. case Failure(exception) => logger.error(s"$exception")
  150. case Success(value) =>
  151. logger.info(s"$value")
  152. val time: Long = (System.currentTimeMillis() - startTime) / 100
  153. logger.info(s"elapsed time: $time")
  154. }
  155. }
  156. override def getAllTvSeries(): Unit = {
  157. val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = titleBasics)
  158. val sink: Sink[TvSerie, Future[Done]] = buildAllTvSeriesSink(logger = logger)
  159. val startingTime: Long = System.currentTimeMillis()
  160. //graph sink->flow->sink
  161. source
  162. .via(flow = buildTvSerieFlow())
  163. .runWith(sink = sink)
  164. .andThen {
  165. case Success(value) =>
  166. val elapsedTime: Long = (System.currentTimeMillis() - startingTime) / 1000
  167. logger.info(s"$value: successfully processing file, elapsed time $titleBasics: $elapsedTime sec")
  168. case Failure(error: Error) => logger.error(s"$error")
  169. }
  170. }
  171. }

Powered by TurnKey Linux.