package fr.natan.akkastreamfileprocessingapi.service import akka.actor.ActorSystem import akka.stream.scaladsl.{Flow, Sink, Source} import akka.{Done, NotUsed} import com.typesafe.scalalogging.slf4j.Logger import fr.natan.akkastreamfileprocessingapi.datasource.Datasource.{nameBasics, titleBasics} import fr.natan.akkastreamfileprocessingapi.models.Models.{Person, TvSeries} import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamComponents.{buildAndValidateSource, buildPersonFlow, buildPersonSink, buildSource, buildTvSerieFlow, buildTvSeriesSink, filterByMoviePrimaryTitleFlow, filterByPersonIdFlow, filterByPersonNameFlow} import org.slf4j.LoggerFactory import org.springframework.stereotype.Component import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Failure, Success} @Component class AkkaStreamFileProcessingImpl extends AkkaStreamFileProcessing { implicit val actorSystem: ActorSystem = ActorSystem("AkkaStreamActor") implicit val logger: Logger = Logger(LoggerFactory.getLogger(this.getClass)) override def getAllMovies(): Unit = { val source: Source[Map[String, String], NotUsed] = buildAndValidateSource(inputFile = titleBasics) val sink: Sink[TvSeries, Future[Done]] = buildTvSeriesSink(logger = logger) val startingTime: Long = System.currentTimeMillis() //graph sink->flow->sink source .via(flow = buildTvSerieFlow()) .runWith(sink = sink) .andThen { case Success(value) => val elapsedTime: Long = (System.currentTimeMillis() - startingTime) / 1000 logger.info(s"$value: successfully processing file, elapsed time $titleBasics: $elapsedTime sec") case Failure(error: Error) => logger.error(s"$error") } } override def getMoviesByTitle(moviePrimaryTitle: String): Unit = { val tvSeriesSource: Source[Map[String, String], NotUsed] = buildAndValidateSource(inputFile = titleBasics) val tvSeriesSink: Sink[TvSeries, Future[Done]] = buildTvSeriesSink(logger = logger) val filterByMovieTitleFlow: Flow[Map[String, String], TvSeries, NotUsed] = filterByMoviePrimaryTitleFlow(moviePrimaryTitle = moviePrimaryTitle) val startTime: Long = System.currentTimeMillis() val listTvSeries: Future[Done] = tvSeriesSource .via(flow = filterByMovieTitleFlow) .runWith(sink = tvSeriesSink) .andThen { case Success(value) => val elapsedTime: Long = (System.currentTimeMillis() - startTime) / 1000 logger.info(s"$value: successfully processing file, elapsed time: $elapsedTime sec") case Failure(error: Error) => logger.error(s"$error") } } override def getAllPersons(): Unit = { val personSource: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics) val personSink: Sink[Person, Future[Done]] = buildPersonSink(logger = logger) //graph val startTime: Long = System.currentTimeMillis() personSource .via(flow = buildPersonFlow()) .runWith(sink = personSink) .andThen { case Success(value) => val elapsedTime: Long = (System.currentTimeMillis() - startTime) / 1000 logger.info(s"$value: successfully processing, elapsed time: $elapsedTime sec") case Failure(error: Error) => logger.error(s"$error") } } override def getPersonById(nconst: String): Unit = { val source: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics) val startTime: Long = System.currentTimeMillis() source .via(flow = filterByPersonIdFlow(nconst = nconst)) .runWith(sink = buildPersonSink(logger = logger)) .andThen { case Success(value) => val elapsedTime: Long = (System.currentTimeMillis()-startTime)/1000 logger.info(s"$value: Successfully processed, elapsed time: $elapsedTime") case Failure(exception) => logger.error(s"$exception: Fail") } } override def getPersonByName(primaryName: String): Unit = { val source: Source[Map[String, String], NotUsed] = buildSource(inputFile = nameBasics) source .via( flow = filterByPersonNameFlow(personName = primaryName) ) .runWith(sink = buildPersonSink(logger = logger)) .andThen { case Failure(exception) => logger.info(s"$exception") case Success(value) => logger.info(s"$value: Successufully processing") } } }