Skip to content

Commit 8eaa9ae

Browse files
ecandreevnoorul
authored andcommitted
fix(jobserver): return 404 for deletion of non existing binary (spark-jobserver#979)
* Return 404 in case of deletion of non existing binary * Add test for this case Previous if one tried to delete a non existing library exception was thrown. This behavior differs from the behavior of contexts and jobs in the same situation (there 404 is returned)
1 parent 6b871e8 commit 8eaa9ae

File tree

6 files changed

+23
-3
lines changed

6 files changed

+23
-3
lines changed

job-server/src/main/scala/spark/jobserver/BinaryManager.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import java.nio.file.{Files, Paths}
1111
import scala.concurrent.Future
1212
import scala.util.{Failure, Success, Try}
1313
import spark.jobserver.common.akka.InstrumentedActor
14+
import spark.jobserver.util.NoSuchBinaryException
1415

1516
// Messages to JarManager actor
1617

@@ -32,6 +33,7 @@ case class StoreLocalBinaries(localBinaries: Map[String, (BinaryType, String)])
3233
case object InvalidBinary
3334
case object BinaryStored
3435
case object BinaryDeleted
36+
case object NoSuchBinary
3537
case class BinaryStorageFailure(ex: Throwable)
3638
case class BinaryDeletionFailure(ex: Throwable)
3739

@@ -109,7 +111,10 @@ class BinaryManager(jobDao: ActorRef) extends InstrumentedActor {
109111
logger.info(s"Deleting binary $appName")
110112
deleteBinary(appName).map {
111113
case Success(_) => BinaryDeleted
112-
case Failure(ex) => BinaryDeletionFailure(ex)
114+
case Failure(ex) => ex match {
115+
case e: NoSuchBinaryException => NoSuchBinary
116+
case _ => BinaryDeletionFailure(ex)
117+
}
113118
}.pipeTo(sender)
114119
}
115120
}

job-server/src/main/scala/spark/jobserver/WebApi.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ class WebApi(system: ActorSystem,
267267
respondWithMediaType(MediaTypes.`application/json`) { ctx =>
268268
future.map {
269269
case BinaryDeleted => ctx.complete(StatusCodes.OK)
270+
case NoSuchBinary => notFound(ctx, s"can't find binary with name $appName")
270271
}.recover {
271272
case e: Exception => ctx.complete(500, errMap(e, "ERROR"))
272273
}
@@ -353,7 +354,7 @@ class WebApi(system: ActorSystem,
353354
case WebUIForContext(name, Some(url)) =>
354355
ctx.complete(200, Map("context" -> contextName, "url" -> url))
355356
case WebUIForContext(name, None) => ctx.complete(200, Map("context" -> contextName))
356-
case NoSuchContext => ctx.complete(404, s"can't find context with name $contextName")
357+
case NoSuchContext => notFound(ctx, s"can't find context with name $contextName")
357358

358359
}.recover {
359360
case e: Exception => ctx.complete(500, errMap(e, "ERROR"))

job-server/src/main/scala/spark/jobserver/io/JobSqlDAO.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import slick.driver.JdbcProfile
2121
import slick.lifted.ProvenShape.proveShapeOf
2222
import spark.jobserver.JobManagerActor.ContextTerminatedException
2323
import spray.http.ErrorInfo
24+
import spark.jobserver.util.NoSuchBinaryException
2425

2526
class JobSqlDAO(config: Config) extends JobDAO with FileCacher {
2627
val slickDriverClass = config.getString("spark.jobserver.sqldao.slick-driver")
@@ -159,7 +160,7 @@ class JobSqlDAO(config: Config) extends JobDAO with FileCacher {
159160
*/
160161
override def deleteBinary(appName: String): Unit = {
161162
if (Await.result(deleteBinaryInfo(appName), 60 seconds) == 0) {
162-
throw new SlickException(s"Failed to delete binary: $appName from database")
163+
throw new NoSuchBinaryException(appName)
163164
}
164165
cleanCacheBinaries(appName)
165166
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package spark.jobserver.util
2+
3+
case class NoSuchBinaryException(private val appName: String) extends Exception {
4+
private val message = s"can't find binary: $appName in database";
5+
}

job-server/src/test/scala/spark/jobserver/WebApiMainRoutesSpec.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ class WebApiMainRoutesSpec extends WebApiSpec {
104104
status should be (OK)
105105
}
106106
}
107+
108+
it("should respond with 404 Not Found if binary was not found during deletion") {
109+
Delete("/binaries/badbinary") ~> sealRoute(routes) ~> check {
110+
status should be (NotFound)
111+
}
112+
}
107113
}
108114

109115
describe("list jobs") {

job-server/src/test/scala/spark/jobserver/WebApiSpec.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import scala.concurrent.{Await, Future}
2020
import scala.util.{Failure, Success}
2121
import java.util.concurrent.TimeUnit
2222
import scala.concurrent.duration.Duration
23+
import spark.jobserver.util.NoSuchBinaryException
2324

2425
// Tests web response codes and formatting
2526
// Does NOT test underlying Supervisor / JarManager functionality
@@ -136,6 +137,7 @@ with ScalatestRouteTest with HttpService with ScalaFutures with SprayJsonSupport
136137
case StoreBinary("daofail", _, _) => sender ! BinaryStorageFailure(new Exception("DAO failed to store"))
137138
case StoreBinary(_, _, _) => sender ! BinaryStored
138139

140+
case DeleteBinary("badbinary") => sender ! NoSuchBinary
139141
case DeleteBinary(_) => sender ! BinaryDeleted
140142

141143
case DataManagerActor.StoreData("errorfileToRemove", _) => sender ! DataManagerActor.Error

0 commit comments

Comments
 (0)