All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
pl.touk.nussknacker.ui.api.ProcessReportResources.scala Maven / Gradle / Ivy
package pl.touk.nussknacker.ui.api
import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model._
import akka.http.scaladsl.server._
import akka.http.scaladsl.unmarshalling.Unmarshaller
import akka.http.scaladsl.util.FastFuture
import akka.stream.Materializer
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.syntax._
import pl.touk.nussknacker.engine.api.graph.ScenarioGraph
import pl.touk.nussknacker.engine.api.process.ProcessName
import pl.touk.nussknacker.processCounts._
import pl.touk.nussknacker.ui.process.ProcessService
import pl.touk.nussknacker.ui.process.marshall.CanonicalProcessConverter
import pl.touk.nussknacker.ui.process.repository.FetchingProcessRepository
import pl.touk.nussknacker.ui.processreport.{ProcessCounter, RawCount}
import pl.touk.nussknacker.ui.security.api.LoggedUser
import java.time.{Instant, OffsetDateTime}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try
class ProcessReportResources(
countsReporter: CountsReporter[Future],
processCounter: ProcessCounter,
processRepository: FetchingProcessRepository[Future],
protected val processService: ProcessService
)(implicit val ec: ExecutionContext)
extends Directives
with FailFastCirceSupport
with RouteWithUser
with ProcessDirectives {
private implicit val offsetDateTimeToInstant: Unmarshaller[String, Instant] = new Unmarshaller[String, Instant] {
override def apply(value: String)(implicit ec: ExecutionContext, materializer: Materializer): Future[Instant] = {
FastFuture(Try(OffsetDateTime.parse(value).toInstant))
}
}
def securedRoute(implicit loggedUser: LoggedUser): Route = {
path("processCounts" / ProcessNameSegment) { processName =>
(get & processId(processName) & parameters(
Symbol("dateFrom").as[Instant].optional,
Symbol("dateTo").as[Instant].optional
)) { (processId, dateFrom, dateTo) =>
val request = prepareRequest(dateFrom, dateTo)
complete {
processRepository
.fetchLatestProcessDetailsForProcessId[ScenarioGraph](processId.id)
.flatMap[ToResponseMarshallable] {
case Some(process) => computeCounts(processName, process.json, process.isFragment, request)
case None => Future.successful(HttpResponse(status = StatusCodes.NotFound, entity = "Scenario not found"))
}
}
}
}
}
private def prepareRequest(dateFromO: Option[Instant], dateToO: Option[Instant]): CountsRequest = {
val dateTo = dateToO
.filterNot(_.isAfter(Instant.now()))
.getOrElse(Instant.now())
dateFromO match {
case Some(dateFrom) =>
RangeCount(dateFrom, dateTo)
case None =>
ExecutionCount(dateTo)
}
}
private def computeCounts(
processName: ProcessName,
scenarioGraph: ScenarioGraph,
isFragment: Boolean,
countsRequest: CountsRequest
)(implicit loggedUser: LoggedUser): Future[ToResponseMarshallable] = {
countsReporter
.prepareRawCounts(processName, countsRequest)
.map(computeFinalCounts(processName, scenarioGraph, isFragment, _))
.recover { case CannotFetchCountsError(msg) =>
HttpResponse(status = StatusCodes.BadRequest, entity = msg)
}
}
private def computeFinalCounts(
processName: ProcessName,
scenarioGraph: ScenarioGraph,
isFragment: Boolean,
nodeCountFunction: String => Option[Long]
)(implicit loggedUser: LoggedUser): ToResponseMarshallable = {
val computedCounts = processCounter.computeCounts(
CanonicalProcessConverter.fromScenarioGraph(scenarioGraph, processName),
isFragment,
nodeId => nodeCountFunction(nodeId).map(count => RawCount(count, 0))
)
computedCounts.asJson
}
}