-
Notifications
You must be signed in to change notification settings - Fork 265
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
twitter-server: Add c.t.server.Hook#onExit lifecycle callback
Problem There may be cases where a Hook needs to run in the `App#onExit` lifecycle. Solution Add an `onExit` callback function which can be implemented by a `c.t.server.Hook` and implement calling it in the Hooks trait which loads and fires service-loaded hooks. Result A `c.t.server.Hook` can define logic which will be triggered during the `onExit` lifecycle phase of an App. Differential Revision: https://phabricator.twitter.biz/D198379
- Loading branch information
Showing
8 changed files
with
154 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.twitter.server | ||
|
||
/** | ||
* Defines a hook into an [[com.twitter.app.App]]. | ||
*/ | ||
abstract class Hook { | ||
|
||
/** | ||
* Executed in `App#premain` which is right before the user's main is invoked. | ||
*/ | ||
def premain(): Unit = () | ||
|
||
/** | ||
* Executed in `App#onExit` which is when shutdown is requested. All registered exit hooks | ||
* run in parallel and are executed after all `App#postmain` functions complete. | ||
*/ | ||
def onExit(): Unit = () | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.twitter.server | ||
|
||
import com.twitter.app.App | ||
|
||
/** | ||
* Create a new hook for the given App. NewHooks are service-loaded. | ||
* | ||
* To use, extend the [[NewHook]] trait and implement an apply method which | ||
* returns a [[Hook]] implementation, e.g., | ||
* | ||
* Add the Hook as a service-loaded class in | ||
* /META-INF/services/com.twitter.server.NewHook | ||
* | ||
* {{{ | ||
* class MyHook extends NewHook { | ||
* def apply(app: App) = new Hook { | ||
* | ||
* override def premain(): Unit = ??? | ||
* | ||
* override def onExit(): Unit = ??? | ||
* } | ||
* } | ||
* }}} | ||
* | ||
* @see [[com.twitter.server.Hook]] | ||
* @see [[com.twitter.finagle.util.LoadService]] | ||
*/ | ||
trait NewHook extends (App => Hook) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,20 @@ | ||
junit_tests( | ||
dependencies=[ | ||
'3rdparty/jvm/junit:junit', | ||
'3rdparty/jvm/org/mockito:mockito-all', | ||
'3rdparty/jvm/org/scala-lang:scala-library', | ||
'3rdparty/jvm/org/scalacheck:scalacheck', | ||
'finagle/finagle-core/src/main/scala:scala', | ||
'finagle/finagle-http/src/main/scala', | ||
'twitter-server/server/src/main/scala', | ||
'util/util-app/src/main/scala:scala', | ||
'util/util-core/src/main/scala:scala', | ||
'util/util-lint/src/main/scala:scala', | ||
'util/util-slf4j-api/src/main/scala:scala', | ||
'util/util-stats/src/main/scala:scala', | ||
], | ||
fatal_warnings=False, | ||
sources=rglobs('*.java') | ||
) | ||
sources = rglobs("*.java"), | ||
fatal_warnings = False, | ||
dependencies = [ | ||
"3rdparty/jvm/junit", | ||
"3rdparty/jvm/org/mockito:mockito-all", | ||
"3rdparty/jvm/org/scala-lang:scala-library", | ||
"3rdparty/jvm/org/scalacheck", | ||
"3rdparty/jvm/org/slf4j:slf4j-api", | ||
"3rdparty/jvm/org/slf4j:slf4j-nop", | ||
"finagle/finagle-core/src/main/scala", | ||
"finagle/finagle-http/src/main/scala", | ||
"twitter-server/server/src/main/scala", | ||
"util/util-app/src/main/scala", | ||
"util/util-core/src/main/scala", | ||
"util/util-lint/src/main/scala", | ||
"util/util-slf4j-api/src/main/scala", | ||
"util/util-stats/src/main/scala", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.twitter.server | ||
|
||
import org.scalatest.FunSuite | ||
import scala.collection.mutable | ||
|
||
class OnExitHook1 extends Hook { | ||
override def onExit(): Unit = { | ||
throw new Exception("onExit 1") | ||
} | ||
} | ||
|
||
class OnExitHook2 extends Hook { | ||
override def onExit(): Unit = { | ||
throw new Exception("onExit 2") | ||
} | ||
} | ||
|
||
class HookTestTwitterServer(hooks: Seq[Hook]) extends TwitterServer { | ||
override val defaultAdminPort = 0 | ||
|
||
val bootstrapSeq: mutable.MutableList[Symbol] = mutable.MutableList.empty[Symbol] | ||
|
||
def main(): Unit = { | ||
bootstrapSeq += 'Main | ||
} | ||
|
||
override def exitOnError(throwable: Throwable): Unit = { | ||
throw throwable | ||
} | ||
|
||
init { | ||
bootstrapSeq += 'Init | ||
} | ||
|
||
premain { | ||
bootstrapSeq += 'PreMain | ||
for (hook <- hooks) | ||
hook.premain() | ||
} | ||
|
||
onExit { | ||
bootstrapSeq += 'Exit | ||
} | ||
|
||
for (hook <- hooks) | ||
onExit { hook.onExit() } | ||
|
||
postmain { | ||
bootstrapSeq += 'PostMain | ||
} | ||
} | ||
|
||
class HookTest extends FunSuite { | ||
|
||
val hooks: Seq[Hook] = Seq(new OnExitHook1(), new OnExitHook2()) | ||
|
||
test("Hooks which error in OnExit are properly captured in onExit blocks") { | ||
val twitterServer = new HookTestTwitterServer(hooks) | ||
|
||
val e = intercept[Exception] { | ||
twitterServer.main(args = Array.empty[String]) | ||
} | ||
|
||
assert(e.getSuppressed.length == 2) | ||
assert( | ||
twitterServer.bootstrapSeq == | ||
Seq('Init, 'PreMain, 'Main, 'PostMain, 'Exit) | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters