Brak opisu

AkkaStreamFileProcessingImpl.scala 11KB

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

Powered by TurnKey Linux.