From 9bfbf10ceacedcbd544592806def0dbceb8510a6 Mon Sep 17 00:00:00 2001 From: Rich Dougherty Date: Tue, 22 Jan 2013 22:54:09 +1300 Subject: [PATCH] Add 'requiring': like 'ensuring' but with 'require' semantics. Fixes #2798 --- .../src/main/scala/akka/util/Helpers.scala | 44 ++++++++++++ .../scala/akka/cluster/ClusterSettings.scala | 67 ++++++++----------- 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/akka-actor/src/main/scala/akka/util/Helpers.scala b/akka-actor/src/main/scala/akka/util/Helpers.scala index d071829148..c0963b30fa 100644 --- a/akka-actor/src/main/scala/akka/util/Helpers.scala +++ b/akka-actor/src/main/scala/akka/util/Helpers.scala @@ -46,4 +46,48 @@ object Helpers { if (next == 0) sb.toString else base64(next, sb) } + + /** + * Implicit class providing `requiring` methods. This class is based on + * `Predef.ensuring` in the Scala standard library. The difference is that + * this class's methods throw `IllegalArgumentException`s rather than + * `AssertionError`s. + * + * An example adapted from `Predef`'s documentation: + * {{{ + * import akka.util.Helpers.Requiring + * + * def addNaturals(nats: List[Int]): Int = { + * require(nats forall (_ >= 0), "List contains negative numbers") + * nats.foldLeft(0)(_ + _) + * } requiring(_ >= 0) + * }}} + * + * @param value The value to check. + */ + @inline final implicit class Requiring[A](val value: A) extends AnyVal { + /** + * Check that a condition is true. If true, return `value`, otherwise throw + * an `IllegalArgumentException` with the given message. + * + * @param cond The condition to check. + * @param msg The message to report if the condition isn't met. + */ + @inline def requiring(cond: Boolean, msg: ⇒ Any): A = { + require(cond, msg) + value + } + + /** + * Check that a condition is true for the `value`. If true, return `value`, + * otherwise throw an `IllegalArgumentException` with the given message. + * + * @param cond The function used to check the `value`. + * @param msg The message to report if the condition isn't met. + */ + @inline def requiring(cond: A ⇒ Boolean, msg: ⇒ Any): A = { + require(cond(value), msg) + value + } + } } diff --git a/akka-cluster/src/main/scala/akka/cluster/ClusterSettings.scala b/akka-cluster/src/main/scala/akka/cluster/ClusterSettings.scala index 7ccf7e48a8..eced8bae97 100644 --- a/akka-cluster/src/main/scala/akka/cluster/ClusterSettings.scala +++ b/akka-cluster/src/main/scala/akka/cluster/ClusterSettings.scala @@ -11,6 +11,7 @@ import akka.ConfigurationException import akka.actor.Address import akka.actor.AddressFromURIString import akka.dispatch.Dispatchers +import akka.util.Helpers.Requiring import scala.concurrent.duration.FiniteDuration import akka.japi.Util.immutableSeq @@ -18,47 +19,36 @@ class ClusterSettings(val config: Config, val systemName: String) { import config._ final val FailureDetectorThreshold: Double = { - val x = getDouble("akka.cluster.failure-detector.threshold") - require(x > 0.0, "failure-detector.threshold must be > 0") - x - } + getDouble("akka.cluster.failure-detector.threshold") + } requiring (_ > 0.0, "failure-detector.threshold must be > 0") final val FailureDetectorMaxSampleSize: Int = { - val n = getInt("akka.cluster.failure-detector.max-sample-size") - require(n > 0, "failure-detector.max-sample-size must be > 0"); n - } + getInt("akka.cluster.failure-detector.max-sample-size") + } requiring (_ > 0, "failure-detector.max-sample-size must be > 0") final val FailureDetectorImplementationClass: String = getString("akka.cluster.failure-detector.implementation-class") final val FailureDetectorMinStdDeviation: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.failure-detector.min-std-deviation"), MILLISECONDS) - require(d > Duration.Zero, "failure-detector.min-std-deviation must be > 0"); d - } + Duration(getMilliseconds("akka.cluster.failure-detector.min-std-deviation"), MILLISECONDS) + } requiring (_ > Duration.Zero, "failure-detector.min-std-deviation must be > 0") final val FailureDetectorAcceptableHeartbeatPause: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.failure-detector.acceptable-heartbeat-pause"), MILLISECONDS) - require(d >= Duration.Zero, "failure-detector.acceptable-heartbeat-pause must be >= 0"); d - } + Duration(getMilliseconds("akka.cluster.failure-detector.acceptable-heartbeat-pause"), MILLISECONDS) + } requiring (_ >= Duration.Zero, "failure-detector.acceptable-heartbeat-pause must be >= 0") final val HeartbeatInterval: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-interval"), MILLISECONDS) - require(d > Duration.Zero, "failure-detector.heartbeat-interval must be > 0"); d - } + Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-interval"), MILLISECONDS) + } requiring (_ > Duration.Zero, "failure-detector.heartbeat-interval must be > 0") final val HeartbeatRequestDelay: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-request.grace-period"), MILLISECONDS) - require(d > Duration.Zero, "failure-detector.heartbeat-request.grace-period must be > 0"); d - } + Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-request.grace-period"), MILLISECONDS) + } requiring (_ > Duration.Zero, "failure-detector.heartbeat-request.grace-period must be > 0") final val HeartbeatExpectedResponseAfter: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-request.expected-response-after"), MILLISECONDS) - require(d > Duration.Zero, "failure-detector.heartbeat-request.expected-response-after > 0"); d - } + Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-request.expected-response-after"), MILLISECONDS) + } requiring (_ > Duration.Zero, "failure-detector.heartbeat-request.expected-response-after > 0") final val HeartbeatRequestTimeToLive: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-request.time-to-live"), MILLISECONDS) - require(d > Duration.Zero, "failure-detector.heartbeat-request.time-to-live > 0"); d - } + Duration(getMilliseconds("akka.cluster.failure-detector.heartbeat-request.time-to-live"), MILLISECONDS) + } requiring (_ > Duration.Zero, "failure-detector.heartbeat-request.time-to-live > 0") final val NumberOfEndHeartbeats: Int = { - val n = getInt("akka.cluster.failure-detector.nr-of-end-heartbeats") - require(n > 0, "failure-detector.nr-of-end-heartbeats must be > 0"); n - } + getInt("akka.cluster.failure-detector.nr-of-end-heartbeats") + } requiring (_ > 0, "failure-detector.nr-of-end-heartbeats must be > 0") final val MonitoredByNrOfMembers: Int = { - val n = getInt("akka.cluster.failure-detector.monitored-by-nr-of-members") - require(n > 0, "failure-detector.monitored-by-nr-of-members must be > 0"); n - } + getInt("akka.cluster.failure-detector.monitored-by-nr-of-members") + } requiring (_ > 0, "failure-detector.monitored-by-nr-of-members must be > 0") final val SeedNodes: immutable.IndexedSeq[Address] = immutableSeq(getStringList("akka.cluster.seed-nodes")).map { case AddressFromURIString(addr) ⇒ addr }.toVector @@ -71,9 +61,8 @@ class ClusterSettings(val config: Config, val systemName: String) { final val AutoJoin: Boolean = getBoolean("akka.cluster.auto-join") final val AutoDown: Boolean = getBoolean("akka.cluster.auto-down") final val MinNrOfMembers: Int = { - val n = getInt("akka.cluster.min-nr-of-members") - require(n > 0, "min-nr-of-members must be > 0"); n - } + getInt("akka.cluster.min-nr-of-members") + } requiring (_ > 0, "min-nr-of-members must be > 0") final val JmxEnabled: Boolean = getBoolean("akka.cluster.jmx.enabled") final val UseDispatcher: String = getString("akka.cluster.use-dispatcher") match { case "" ⇒ Dispatchers.DefaultDispatcherId @@ -90,14 +79,12 @@ class ClusterSettings(val config: Config, val systemName: String) { final val MetricsEnabled: Boolean = getBoolean("akka.cluster.metrics.enabled") final val MetricsCollectorClass: String = getString("akka.cluster.metrics.collector-class") final val MetricsInterval: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.metrics.collect-interval"), MILLISECONDS) - require(d > Duration.Zero, "metrics.collect-interval must be > 0"); d - } + Duration(getMilliseconds("akka.cluster.metrics.collect-interval"), MILLISECONDS) + } requiring (_ > Duration.Zero, "metrics.collect-interval must be > 0") final val MetricsGossipInterval: FiniteDuration = Duration(getMilliseconds("akka.cluster.metrics.gossip-interval"), MILLISECONDS) final val MetricsMovingAverageHalfLife: FiniteDuration = { - val d = Duration(getMilliseconds("akka.cluster.metrics.moving-average-half-life"), MILLISECONDS) - require(d > Duration.Zero, "metrics.moving-average-half-life must be > 0"); d - } + Duration(getMilliseconds("akka.cluster.metrics.moving-average-half-life"), MILLISECONDS) + } requiring (_ > Duration.Zero, "metrics.moving-average-half-life must be > 0") } case class CircuitBreakerSettings(maxFailures: Int, callTimeout: FiniteDuration, resetTimeout: FiniteDuration)