Нет описания

AkkaStreamFileProcessingImpl.scala 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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.{
  7. nameBasics, titleBasics, titlePrincipalsBasics
  8. }
  9. import fr.natan.akkastreamfileprocessingapi.models.Models.{Person, TvSerie}
  10. import fr.natan.akkastreamfileprocessingapi.models.ModelsBuilder.buildPersonModel
  11. import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{
  12. buildAllPersonsSink,
  13. buildAllTvSeriesSink,
  14. buildAndValidateSource,
  15. buildPersonFlow,
  16. buildSource,
  17. buildTvSerieFlow,
  18. filterPersonByIdFlow,
  19. filterPersonByNameFlow,
  20. filterTvSerieByIdFlow,
  21. filterTvSerieByPrimaryTitleFlow
  22. }
  23. import org.slf4j.LoggerFactory
  24. import org.springframework.stereotype.Component
  25. import scala.concurrent.ExecutionContext.Implicits.global
  26. import scala.concurrent.Future
  27. import scala.language.postfixOps
  28. import scala.util.{Failure, Success}
  29. //noinspection SpellCheckingInspection
  30. @Component
  31. class AkkaStreamFileProcessingImpl extends AkkaStreamFileProcessingFuture {
  32. implicit val actorSystem: ActorSystem = ActorSystem("AkkaStreamActor")
  33. implicit val logger: Logger = Logger(LoggerFactory.getLogger(this.getClass))
  34. override def getPersonByIdFuture(personID: String): Future[Person] = {
  35. val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  36. val personFuture: Future[Person] = source
  37. .via(flow = filterPersonByIdFlow(personID = personID))
  38. .runWith(Sink.head)
  39. personFuture.andThen({
  40. case Failure(exception) => logger.info(s"$exception")
  41. case Success(value:Person) => logger.info(s"$value")
  42. })
  43. personFuture
  44. }
  45. override def getPersonByNameFuture(primaryName: String): Future[Person] = {
  46. val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  47. val personFuture: Future[Person] = source
  48. .via(flow = filterPersonByNameFlow(primaryName = primaryName))
  49. .runWith(Sink.head)
  50. personFuture.onComplete({
  51. case Failure(exception) => logger.error(s"$exception")
  52. case Success(value: Person) => logger.info(s"$value")
  53. logger.info("SUCCESS")
  54. })
  55. personFuture
  56. }
  57. override def getTvSerieByIdFuture(tvSerieID: String): Future[TvSerie] = {
  58. val source: Source[Map[String, String], _] = buildSource(inputFile = titleBasics)
  59. val tvSerieFuture: Future[TvSerie] = source
  60. .via(flow = filterTvSerieByIdFlow(tvSerieID = tvSerieID))
  61. .runWith(Sink.head)
  62. tvSerieFuture.onComplete({
  63. case Failure(exception) => logger.info(s"$exception")
  64. case Success(value: TvSerie) => logger.info(s"$value")
  65. })
  66. tvSerieFuture
  67. }
  68. override def getTvSeriesByPrimaryTitleFuture(tvSeriePrimaryTitle: String): Future[IndexedSeq[TvSerie]] = {
  69. val tvSeriesSource: Source[Map[String, String], _] = buildAndValidateSource(inputFile = titleBasics)
  70. val tvSriesFuture: Future[IndexedSeq[TvSerie]] = tvSeriesSource
  71. .via(flow = filterTvSerieByPrimaryTitleFlow(tvSeriePrimaryTitle = tvSeriePrimaryTitle))
  72. .runWith(Sink.collection)
  73. tvSriesFuture.onComplete({
  74. case Failure(exception) => logger.info(s"$exception")
  75. case Success(value: IndexedSeq[TvSerie]) =>
  76. value.foreach((tvSrie: TvSerie) => logger.info(s"$tvSrie"))
  77. logger.info("SUCCESS")
  78. })
  79. tvSriesFuture
  80. }
  81. private def getTvSerieIdByPrimaryTitle(primaryTitle: String): Future[Option[String]] = {
  82. val source: Source[Map[String, String], _] = buildSource(inputFile = titleBasics)
  83. val tvSerieIdFuture: Future[Option[String]] = source
  84. .filter((rowMap: Map[String, String]) => {
  85. rowMap.getOrElse(key = "primaryTitle", default = "") == primaryTitle
  86. })
  87. .map((rowMap: Map[String, String]) => rowMap.get("tconst"))
  88. .runWith(Sink.head)
  89. tvSerieIdFuture
  90. }
  91. private def getListOfPersonsIDByTvSerieID(tvSerieIdFuture: Future[Option[String]]): Future[IndexedSeq[Option[String]]] = {
  92. val source: Source[Map[String, String], _] = buildSource(inputFile = titlePrincipalsBasics)
  93. val personsIDsFuture: Future[IndexedSeq[Option[String]]] = source
  94. .filter((rowMaps: Map[String, String]) => {
  95. rowMaps.getOrElse(key = "tconst", default = "") == tvSerieIdFuture.value.get.get.get
  96. })
  97. .map((rowMap: Map[String, String]) => {
  98. rowMap.get(key = "nconst")
  99. })
  100. .runWith(Sink.collection)
  101. personsIDsFuture
  102. }
  103. private def getListOfPersonsForTvSerie(listPersonsIDsFuture: Future[IndexedSeq[Option[String]]]): Future[IndexedSeq[Person]] = {
  104. val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  105. val personsFuture: Future[IndexedSeq[Person]] = source
  106. .filter((rowMaps: Map[String, String]) => {
  107. listPersonsIDsFuture.value.get.get.contains(rowMaps.get(key = "nconst"))
  108. })
  109. .map((rowMap: Map[String, String]) => {
  110. buildPersonModel(rowMap)
  111. })
  112. .runWith(Sink.collection)
  113. personsFuture
  114. }
  115. override def getPersonsForTvSerieByTvSerieTitleFuture(tvSeriePrimaryTitle: String): Future[IndexedSeq[Person]] = {
  116. //futures chaining
  117. logger.info("STEP 1/3 START")
  118. val tvSerieIDFuture: Future[Option[String]] = getTvSerieIdByPrimaryTitle(primaryTitle = tvSeriePrimaryTitle)
  119. val finalFuture: Future[IndexedSeq[Person]] =
  120. tvSerieIDFuture.andThen({
  121. case Failure(exception) => logger.error(s"$exception")
  122. case Success(value: Option[String]) =>
  123. logger.info(s"TvSerie ID: $value")
  124. logger.info("STEP 1/3 END")
  125. })
  126. .flatMap({
  127. _ =>
  128. logger.info("STEP 2/3 START")
  129. val listPersonIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(tvSerieIdFuture = tvSerieIDFuture)
  130. listPersonIDsFuture.andThen({
  131. case Failure(exception) => logger.error(s"$exception")
  132. case Success(value) =>
  133. value.foreach((personID: Option[String]) => logger.info(s"Person ID:$personID"))
  134. logger.info("STEP 2/3 END")
  135. })
  136. .flatMap({
  137. _ =>
  138. logger.info("STEP 3/3 START")
  139. val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(listPersonsIDsFuture = listPersonIDsFuture)
  140. personsTeamFuture.andThen({
  141. case Failure(exception) => logger.error(s"$exception")
  142. case Success(value: IndexedSeq[Person]) =>
  143. value.foreach((person: Person) => logger.info(s"${person.toString}"))
  144. logger.info("STEP 3/3 END")
  145. })
  146. })
  147. })
  148. finalFuture
  149. }
  150. private def getTvSerieIDFuture(tvSerieId: String): Future[Option[String]] ={
  151. val source: Source[Map[String, String], _] = buildSource(inputFile = titlePrincipalsBasics)
  152. val tvSerieIdFuture : Future[Option[String]]= source.
  153. filter((rowMap: Map[String, String]) => rowMap.getOrElse(key = "tconst", default = "") == tvSerieId)
  154. .map((rowMap: Map[String, String])=>rowMap.get(key = "tconst"))
  155. .runWith(Sink.head)
  156. tvSerieIdFuture
  157. }
  158. override def getPersonsForTvSerieByTvSerieIdFuture(tvSerieId: String): Future[IndexedSeq[Person]] = {
  159. val tvSerieIdFuture: Future[Option[String]] = getTvSerieIDFuture(tvSerieId = tvSerieId)
  160. logger.info("STEP 1/3")
  161. tvSerieIdFuture.andThen({
  162. case Failure(exception) => logger.error(s"${exception.printStackTrace()}")
  163. case Success(value:Option[String]) =>
  164. logger.info(s"$value")
  165. logger.info("STEP 1/3")
  166. })
  167. .flatMap({
  168. _ => logger.info("STEP 2/3")
  169. val listOfPersonsIDsFuture : Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(tvSerieIdFuture = tvSerieIdFuture)
  170. listOfPersonsIDsFuture.andThen({
  171. case Failure(exception) => logger.error(s"${exception.printStackTrace()}")
  172. case Success(value) =>
  173. value.foreach((personID: Option[String]) => logger.info(s"Person ID:$personID"))
  174. logger.info("STEP 2/3 END")
  175. })
  176. .flatMap({
  177. _ => logger.info("STEP 3/3")
  178. val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(listPersonsIDsFuture = listOfPersonsIDsFuture)
  179. personsTeamFuture.andThen({
  180. case Failure(exception) => logger.error(s"$exception")
  181. case Success(value: IndexedSeq[Person]) =>
  182. value.foreach((person: Person) => logger.info(s"${person.toString}"))
  183. logger.info("STEP 3/3 END")
  184. })
  185. })
  186. })
  187. }
  188. override def getAllPersonsFuture(): Future[Done] = {
  189. val personSource: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
  190. //graph
  191. val startTime: Long = System.currentTimeMillis()
  192. val result: Future[Done] = personSource
  193. .via(flow = buildPersonFlow())
  194. .runWith(sink = buildAllPersonsSink(logger = logger))
  195. result.onComplete {
  196. case Failure(exception) => logger.error(s"$exception")
  197. case Success(value) =>
  198. logger.info(s"$value")
  199. val time: Long = (System.currentTimeMillis() - startTime) / 100
  200. logger.info(s"elapsed time: $time")
  201. }
  202. result
  203. }
  204. override def getAllTvSeriesFuture(): Future[Done] = {
  205. val source: Source[Map[String, String], _] = buildAndValidateSource(inputFile = titleBasics)
  206. val sink: Sink[TvSerie, Future[Done]] = buildAllTvSeriesSink(logger = logger)
  207. val startingTime: Long = System.currentTimeMillis()
  208. //graph sink->flow->sink
  209. val results: Future[Done] = source
  210. .via(flow = buildTvSerieFlow())
  211. .runWith(sink = sink)
  212. .andThen {
  213. case Success(value) =>
  214. val elapsedTime: Long = (System.currentTimeMillis() - startingTime) / 1000
  215. logger.info(s"$value: successfully processing file, elapsed time $titleBasics: $elapsedTime sec")
  216. case Failure(error: Error) => logger.error(s"$error")
  217. }
  218. results
  219. }
  220. }

Powered by TurnKey Linux.