Skip to content

Commit b728f08

Browse files
author
Marcelo Vanzin
committed
[SPARK-7378] [core] Handle deep links to unloaded apps.
The code was treating deep links as if they were attempt IDs, so for example if you tried to load "/history/app1/jobs" directly, that would fail because the code would treat "jobs" as an attempt id. This change modifies the code to try both cases - first without an attempt id, then with it, so that deep links are handled correctly. This assumes that the links in the Spark UI do not clash with the attempt id namespace, though, which is the case for YARN at least, which is the only backend that currently publishes attempt IDs.
1 parent 9f1f9b1 commit b728f08

File tree

1 file changed

+29
-19
lines changed

1 file changed

+29
-19
lines changed

core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -83,31 +83,27 @@ class HistoryServer(
8383
return
8484
}
8585

86-
val appKey =
87-
if (parts.length == 3) {
88-
s"${parts(1)}/${parts(2)}"
89-
} else {
90-
parts(1)
86+
val appId = parts(1)
87+
val attemptId = if (parts.length > 3) Some(parts(2)) else None
88+
89+
// Since we may have applications with multiple attempts mixed with applications with a
90+
// single attempt, we need to try both. Try the single-attempt route first, and if an
91+
// error is raised, then try the multiple attempt route.
92+
if (!loadAppUi(appId, None && (!attemptId.isDefined || !loadAppUi(appId, attemptId)) {
93+
val msg = <div class="row-fluid">Application {appId} not found.</div>
94+
res.setStatus(HttpServletResponse.SC_NOT_FOUND)
95+
UIUtils.basicSparkPage(msg, "Not Found").foreach { n =>
96+
res.getWriter().write(n.toString)
9197
}
98+
return
99+
}
92100

93101
// Note we don't use the UI retrieved from the cache; the cache loader above will register
94102
// the app's UI, and all we need to do is redirect the user to the same URI that was
95103
// requested, and the proper data should be served at that point.
96-
try {
97-
appCache.get(appKey)
98-
res.sendRedirect(res.encodeRedirectURL(req.getRequestURI()))
99-
} catch {
100-
case e: Exception => e.getCause() match {
101-
case nsee: NoSuchElementException =>
102-
val msg = <div class="row-fluid">Application {appKey} not found.</div>
103-
res.setStatus(HttpServletResponse.SC_NOT_FOUND)
104-
UIUtils.basicSparkPage(msg, "Not Found").foreach(
105-
n => res.getWriter().write(n.toString))
106-
107-
case cause: Exception => throw cause
108-
}
109-
}
104+
res.sendRedirect(res.encodeRedirectURL(req.getRequestURI()))
110105
}
106+
111107
// SPARK-5983 ensure TRACE is not supported
112108
protected override def doTrace(req: HttpServletRequest, res: HttpServletResponse): Unit = {
113109
res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED)
@@ -183,6 +179,20 @@ class HistoryServer(
183179
*/
184180
def getProviderConfig(): Map[String, String] = provider.getConfig()
185181

182+
private def loadAppUi(appId: String, attemptId: Option[String]): Boolean = {
183+
try {
184+
appCache.get(appId + attemptId.map { id => s"/$id" }.getOrElse(""))
185+
true
186+
} catch {
187+
case e: Exception => e.getCause() match {
188+
case nsee: NoSuchElementException =>
189+
false
190+
191+
case cause: Exception => throw cause
192+
}
193+
}
194+
}
195+
186196
}
187197

188198
/**

0 commit comments

Comments
 (0)