diff --git a/core/src/main/javascript/app/pages/BackfillCreate.js b/core/src/main/javascript/app/pages/BackfillCreate.js index 19072fbbd..ba52dc831 100644 --- a/core/src/main/javascript/app/pages/BackfillCreate.js +++ b/core/src/main/javascript/app/pages/BackfillCreate.js @@ -137,11 +137,19 @@ class BackfillCreate extends React.Component { throw new SubmissionError({ _error: "No jobs selected" }); return fetch( - `/api/timeseries/backfill?` + - `name=${name}&description=${description || ""}&` + - `jobs=${jobs.join(",")}&priority=${priority}&` + - `startDate=${start.toISOString()}&endDate=${end.toISOString()}`, - { method: "POST", credentials: "include" } + `/api/timeseries/backfill`, + { + method: "POST", + credentials: "include", + body: JSON.stringify({ + name: name, + description: description || "", + jobs: jobs.join(","), + priority: priority, + startDate: start.toISOString(), + endDate: end.toISOString() + }) + } ) .then((response: Response) => { if (!response.ok) return response.text(); diff --git a/timeseries/src/main/scala/com/criteo/cuttle/timeseries/Internal.scala b/timeseries/src/main/scala/com/criteo/cuttle/timeseries/Internal.scala index 48d0f8109..dc0685485 100644 --- a/timeseries/src/main/scala/com/criteo/cuttle/timeseries/Internal.scala +++ b/timeseries/src/main/scala/com/criteo/cuttle/timeseries/Internal.scala @@ -3,11 +3,14 @@ package com.criteo.cuttle.timeseries import com.criteo.cuttle._ import io.circe._ +import io.circe.generic.semiauto._ import cats.syntax.either._ import java.time.Instant +import io.circe.generic.semiauto.deriveDecoder + private[timeseries] object Internal { implicit def jobEncoder[A <: Scheduling]: Encoder[Job[A]] = @@ -21,5 +24,19 @@ private[timeseries] object Internal { Decoder.decodeString.emap { s => Either.catchNonFatal(Instant.parse(s)).leftMap(s => "Instant") } +} +private[timeseries] object BackfillCreate { + import Internal._ + + implicit val decodeBackfillCreate : Decoder[BackfillCreate] = deriveDecoder[BackfillCreate] } + +private[timeseries] case class BackfillCreate( + name : String, + description : String, + jobs : String, + startDate : Instant, + endDate : Instant, + priority : Int + ) diff --git a/timeseries/src/main/scala/com/criteo/cuttle/timeseries/TimeSeriesApp.scala b/timeseries/src/main/scala/com/criteo/cuttle/timeseries/TimeSeriesApp.scala index 48e69d346..045e7affb 100644 --- a/timeseries/src/main/scala/com/criteo/cuttle/timeseries/TimeSeriesApp.scala +++ b/timeseries/src/main/scala/com/criteo/cuttle/timeseries/TimeSeriesApp.scala @@ -17,6 +17,7 @@ import intervals._ import Bound.{Bottom, Finite, Top} import ExecutionStatus._ import com.criteo.cuttle.authentication.AuthenticatedService +import scala.concurrent.ExecutionContext.Implicits.global private[timeseries] trait TimeSeriesApp { self: TimeSeriesScheduler => @@ -426,15 +427,31 @@ private[timeseries] trait TimeSeriesApp { self: TimeSeriesScheduler => private[cuttle] override def privateRoutes(workflow: Workflow[TimeSeries], executor: Executor[TimeSeries], xa: XA): AuthenticatedService = { - case POST at url"/api/timeseries/backfill?name=$name&description=$description&jobs=$jobsString&startDate=$start&endDate=$end&priority=$priority" => - implicit user_ => - val jobIds = jobsString.split(",") - val jobs = workflow.vertices.filter((job: TimeSeriesJob) => jobIds.contains(job.id)) - val startDate = Instant.parse(start) - val endDate = Instant.parse(end) - if (backfillJob(name, description, jobs, startDate, endDate, priority.toInt, xa)) - Ok("ok".asJson) - else - BadRequest("invalid backfill") + + case req @ POST at url"/api/timeseries/backfill" => implicit user => + req.readAs[Json].map( + _.as[BackfillCreate] + .fold( + error => BadRequest("cannot parse request body"), + backfill => { + val jobIds = backfill.jobs.split(",") + val jobs = workflow.vertices + .filter((job: TimeSeriesJob) => jobIds.contains(job.id)) + + if (backfillJob( + backfill.name, + backfill.description, + jobs, + backfill.startDate, + backfill.endDate, + backfill.priority, + xa)) { + Ok("ok".asJson) + } + else { + BadRequest("invalid backfill") + } + }) + ) } }