Нет описания

AkkaStreamFileProcessingImpl.scala 7.7KB

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

Powered by TurnKey Linux.