Skip to content

Conversation

@ajbozarth
Copy link
Member

What changes were proposed in this pull request?

Currently users can kill stages via the web ui but not jobs directly (jobs are killed if one of their stages is). I've added the ability to kill jobs via the web ui. This code change is based on #4823 by @lianhuiwang and updated to work with the latest code matching how stages are currently killed. In general I've copied the kill stage code warning and note comments and all. I also updated applicable tests and documentation.

How was this patch tested?

Manually tested and dev/run-tests

screen shot 2016-10-11 at 4 49 43 pm

@ajbozarth
Copy link
Member Author

@srowen @kayousterhout @tgravescs You have had input or the JIRA or previous PR, could you take a look?

val jobId = Option(request.getParameter("id")).getOrElse("-1").toInt
if (jobId >= 0 && killFlag && jobProgresslistener.activeJobs.contains(jobId)) {
sc.get.cancelJob(jobId)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating an Option only to immediately get the value out of it is poor style, and unnecessary.

val jobId = Option(request.getParameter("id"))
jobId.foreach { id =>
  if (killFlag && jobProgresslistener.activeJobs.contains(id)) {
    sc.get.cancelJob(id)
  }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, there is no need for sc.get. In fact, that's a bug if parent.sc really should be an Option and thus could be None.

sc.foreach(_.cancelJob(id))

Copy link
Contributor

@markhamstra markhamstra Oct 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if the Job isn't actually going to be canceled, then there is no need to delay the page refresh (which I'm not entirely happy with, but I'm not going to try to resolve that issue right now.) So...

sc.foreach { sparkContext =>
  sparkContext.cancelJob(id)
  Thread.sleep(100)
}

And we better make that jobId an Option[Int] instead of an Option[String], so...

val jobId = Option(request.getParameter("id")).map(_.toInt)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this code from StagesTab.scala so I'll fix these issues for both in the morning

@SparkQA
Copy link

SparkQA commented Oct 12, 2016

Test build #66775 has finished for PR 15441 at commit 999f83a.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@ajbozarth
Copy link
Member Author

Addressed @markhamstra comments for both JobsTab and StagesTab

// Do a quick pause here to give Spark time to kill the job so it shows up as
// killed after the refresh. Note that this will block the serving thread so the
// time should be limited in duration.
Thread.sleep(100)
Copy link
Contributor

@markhamstra markhamstra Oct 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're doing the sleep here even if sc is None, but I wouldn't expect that that is even possible or that it is handled completely correctly elsewhere in the Web UI if it actually is possible, so this is likely fine in practice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my thinking, that in the case of sc being None that this code shouldn't be able to be called. Plus by moving the sleep into the if statement it at least only run when an actual kill is attempted.

@SparkQA
Copy link

SparkQA commented Oct 12, 2016

Test build #66843 has finished for PR 15441 at commit c9b2454.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@ajbozarth
Copy link
Member Author

@srowen @tgravescs any chance you'd be able to take a look at this before spark summit?

Copy link
Member

@srowen srowen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is pretty OK, pending a few minor changes.

// Do a quick pause here to give Spark time to kill the job so it shows up as
// killed after the refresh. Note that this will block the serving thread so the
// time should be limited in duration.
Thread.sleep(100)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, in both this and the kill-stage endpoint I wonder why we have a 'terminate' flag at all. What would it mean to call this with terminate=false? it seems like this can be checked once, if at all, at the start of the method. Or just removed, if I'm not missing something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just did some looking into the git history and thats left over from when there wasn't a separate /kill endpoint, so I'll remove that logic in my next commit

connection.setRequestMethod(method)
connection.connect()
val code = connection.getResponseCode()
connection.disconnect()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For total tidiness you might use try-finally here to disconnect on all paths.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might just because it's late and I'm tired but I'm not quite sure where you think the try-finally should be

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just mean

val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setRequestMethod(method)
try {
  connection.connect()
  connection.getResponseCode()
} finally {
  connection.disconnect()
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I didn't know scala could do that (how it returns), still learning new things every day

<td>true</td>
<td>
Allows stages and corresponding jobs to be killed from the web ui.
Allows jobs and stages to be killed from the web ui.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: web ui -> web UI

@ajbozarth
Copy link
Member Author

@srowen I addressed most of your comments except the one about the try-finally I commented on above

@SparkQA
Copy link

SparkQA commented Oct 23, 2016

Test build #67406 has finished for PR 15441 at commit b1e77ba.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA
Copy link

SparkQA commented Oct 23, 2016

Test build #67417 has finished for PR 15441 at commit 0162c81.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@ajbozarth
Copy link
Member Author

@srowen Addressed the try-finally, this look good to go now?

Copy link
Member

@srowen srowen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple minor extra comments

override def row(jobTableRow: JobTableRowData): Seq[Node] = {
val job = jobTableRow.jobData

val killLink = if (killEnabled) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, does this work? there's no 'else' so this becomes an Any and I don't know what happens below when it's rendered as a string. Should it be an empty string otherwise?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, since it's supposed to be html I'll add a else Seq.empty to each instance of this

/** Initialize all components of the server. */
def initialize() {
attachTab(new JobsTab(this))
attachTab(jobsTab)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #15603 which reminds me that these two tabs don't need to be members. They can be locals. You can make the change for both here.

@ajbozarth
Copy link
Member Author

@srowen I addressed your latest comments

Copy link
Member

@srowen srowen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that looks good pending tests.

@SparkQA
Copy link

SparkQA commented Oct 24, 2016

Test build #67465 has finished for PR 15441 at commit 12bc267.

  • This patch fails Spark unit tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@ajbozarth
Copy link
Member Author

Jenkins, retest this please

@SparkQA
Copy link

SparkQA commented Oct 24, 2016

Test build #67471 has finished for PR 15441 at commit 12bc267.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@ajbozarth
Copy link
Member Author

Good to merge? @srowen

@srowen
Copy link
Member

srowen commented Oct 26, 2016

Merged to master

@asfgit asfgit closed this in 5d0f81d Oct 26, 2016
@ajbozarth ajbozarth deleted the spark4411 branch October 26, 2016 15:58
robert3005 pushed a commit to palantir/spark that referenced this pull request Nov 1, 2016
## What changes were proposed in this pull request?

Currently users can kill stages via the web ui but not jobs directly (jobs are killed if one of their stages is). I've added the ability to kill jobs via the web ui. This code change is based on apache#4823 by lianhuiwang and updated to work with the latest code matching how stages are currently killed. In general I've copied the kill stage code warning and note comments and all. I also updated applicable tests and documentation.

## How was this patch tested?

Manually tested and dev/run-tests

![screen shot 2016-10-11 at 4 49 43 pm](https://cloud.githubusercontent.com/assets/13952758/19292857/12f1b7c0-8fd4-11e6-8982-210249f7b697.png)

Author: Alex Bozarth <[email protected]>
Author: Lianhui Wang <[email protected]>

Closes apache#15441 from ajbozarth/spark4411.
uzadude pushed a commit to uzadude/spark that referenced this pull request Jan 27, 2017
## What changes were proposed in this pull request?

Currently users can kill stages via the web ui but not jobs directly (jobs are killed if one of their stages is). I've added the ability to kill jobs via the web ui. This code change is based on apache#4823 by lianhuiwang and updated to work with the latest code matching how stages are currently killed. In general I've copied the kill stage code warning and note comments and all. I also updated applicable tests and documentation.

## How was this patch tested?

Manually tested and dev/run-tests

![screen shot 2016-10-11 at 4 49 43 pm](https://cloud.githubusercontent.com/assets/13952758/19292857/12f1b7c0-8fd4-11e6-8982-210249f7b697.png)

Author: Alex Bozarth <[email protected]>
Author: Lianhui Wang <[email protected]>

Closes apache#15441 from ajbozarth/spark4411.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants