summaryrefslogtreecommitdiffstats
path: root/clustercontroller-utils
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@oath.com>2018-06-22 11:01:22 +0200
committerHåkon Hallingstad <hakon@oath.com>2018-06-22 11:01:22 +0200
commitda8720586341957f15bf6a42b291d879c8569538 (patch)
tree29bb114ffbc6bb5bdd4a048e53845df00f449e08 /clustercontroller-utils
parentd17e36f062c38550a96ccee3e41d7ff5266efecb (diff)
set-node-state timeout in CC
Diffstat (limited to 'clustercontroller-utils')
-rw-r--r--clustercontroller-utils/pom.xml5
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java2
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java43
-rw-r--r--clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java29
-rw-r--r--clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReaderTest.java20
5 files changed, 91 insertions, 8 deletions
diff --git a/clustercontroller-utils/pom.xml b/clustercontroller-utils/pom.xml
index ecfc6df3bd0..e176ce9d1e5 100644
--- a/clustercontroller-utils/pom.xml
+++ b/clustercontroller-utils/pom.xml
@@ -40,6 +40,11 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java
index d583e4ecc27..a28ddb3539b 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/requests/SetUnitStateRequest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.clustercontroller.utils.staterestapi.requests;
+import com.yahoo.time.TimeBudget;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidContentException;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitState;
@@ -62,4 +63,5 @@ public interface SetUnitStateRequest extends UnitRequest {
}
ResponseWait getResponseWait();
+ TimeBudget timeBudget();
}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java
index 3d0856669f1..3c62d87098b 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReader.java
@@ -8,10 +8,16 @@ import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitState;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
+import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
public class JsonReader {
+ public static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(30);
+ public static final Duration MAX_TIMEOUT = Duration.ofHours(1);
+ private static final long MICROS_IN_SECOND = TimeUnit.SECONDS.toMillis(1);
private static class UnitStateImpl implements UnitState {
private final String id;
@@ -37,11 +43,16 @@ public class JsonReader {
final Map<String, UnitState> stateMap;
final SetUnitStateRequest.Condition condition;
final SetUnitStateRequest.ResponseWait responseWait;
- public SetRequestData(Map<String, UnitState> stateMap, SetUnitStateRequest.Condition condition,
- SetUnitStateRequest.ResponseWait responseWait) {
+ final Optional<Duration> timeout;
+
+ public SetRequestData(Map<String, UnitState> stateMap,
+ SetUnitStateRequest.Condition condition,
+ SetUnitStateRequest.ResponseWait responseWait,
+ Optional<Duration> timeout) {
this.stateMap = stateMap;
this.condition = condition;
this.responseWait = responseWait;
+ this.timeout = timeout;
}
}
@@ -98,7 +109,33 @@ public class JsonReader {
}
stateMap.put(type, new UnitStateImpl(code, reason));
}
- return new SetRequestData(stateMap, condition, responseWait);
+
+ final Optional<Duration> timeout = parseTimeout(request.getOption("timeout", null));
+
+ return new SetRequestData(stateMap, condition, responseWait, timeout);
+ }
+
+ public static Optional<Duration> parseTimeout(String timeoutOption) throws InvalidContentException {
+ if (timeoutOption == null) {
+ return Optional.empty();
+ } else {
+ float timeoutSeconds;
+ try {
+ timeoutSeconds = Float.parseFloat(timeoutOption);
+ } catch (NumberFormatException e) {
+ throw new InvalidContentException("value of timeout->" + timeoutOption + " is not a float");
+ }
+
+ if (timeoutSeconds <= 0.0) {
+ return Optional.of(Duration.ZERO);
+ } else if (timeoutSeconds <= MAX_TIMEOUT.getSeconds()) {
+ long micros = Math.round(timeoutSeconds * MICROS_IN_SECOND);
+ long nanoAdjustment = TimeUnit.MILLISECONDS.toNanos(micros % MICROS_IN_SECOND);
+ return Optional.of(Duration.ofSeconds(micros / MICROS_IN_SECOND, nanoAdjustment));
+ } else {
+ throw new InvalidContentException("value of timeout->" + timeoutOption + " exceeds max timeout " + MAX_TIMEOUT);
+ }
+ }
}
}
diff --git a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java
index 71e6bc36de1..2ccfecf3d17 100644
--- a/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java
+++ b/clustercontroller-utils/src/main/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/RestApiHandler.java
@@ -1,19 +1,32 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.clustercontroller.utils.staterestapi.server;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
import com.yahoo.log.LogLevel;
-import com.yahoo.yolean.Exceptions;
+import com.yahoo.time.TimeBudget;
import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequest;
import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpRequestHandler;
import com.yahoo.vespa.clustercontroller.utils.communication.http.HttpResult;
import com.yahoo.vespa.clustercontroller.utils.communication.http.JsonHttpResult;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.StateRestAPI;
-import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.*;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.DeadlineExceededException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidOptionValueException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.OtherMasterException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.StateRestApiException;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.UnknownMasterException;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.SetUnitStateRequest;
import com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.UnitStateRequest;
-import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.*;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.SetResponse;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitResponse;
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.response.UnitState;
+import com.yahoo.yolean.Exceptions;
-import java.util.*;
+import java.time.Clock;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -24,10 +37,12 @@ public class RestApiHandler implements HttpRequestHandler {
private final StateRestAPI restApi;
private final JsonWriter jsonWriter;
private final JsonReader jsonReader = new JsonReader();
+ private final Clock clock;
public RestApiHandler(StateRestAPI restApi) {
this.restApi = restApi;
this.jsonWriter = new JsonWriter();
+ this.clock = Clock.systemUTC();
}
public RestApiHandler setDefaultPathPrefix(String defaultPathPrefix) {
@@ -43,6 +58,8 @@ public class RestApiHandler implements HttpRequestHandler {
@Override
public HttpResult handleRequest(HttpRequest request) {
+ Instant start = clock.instant();
+
try{
final String[] unitPath = createUnitPath(request);
if (request.getHttpOperation().equals(HttpRequest.HttpOp.GET)) {
@@ -73,6 +90,8 @@ public class RestApiHandler implements HttpRequestHandler {
public Condition getCondition() { return setRequestData.condition; }
@Override
public ResponseWait getResponseWait() { return setRequestData.responseWait; }
+ @Override
+ public TimeBudget timeBudget() { return TimeBudget.from(clock, start, setRequestData.timeout); }
});
return new JsonHttpResult().setJson(jsonWriter.createJson(setResponse));
}
@@ -89,7 +108,7 @@ public class RestApiHandler implements HttpRequestHandler {
result.setHttpCode(503, "Service Unavailable");
result.setJson(jsonWriter.createErrorJson(exception.getMessage()));
return result;
- } catch (DeadlineExceededException exception) {
+ } catch (DeadlineExceededException | UncheckedTimeoutException exception) {
logRequestException(request, exception, Level.WARNING);
JsonHttpResult result = new JsonHttpResult();
result.setHttpCode(504, "Gateway Timeout");
diff --git a/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReaderTest.java b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReaderTest.java
new file mode 100644
index 00000000000..bf47a6605a2
--- /dev/null
+++ b/clustercontroller-utils/src/test/java/com/yahoo/vespa/clustercontroller/utils/staterestapi/server/JsonReaderTest.java
@@ -0,0 +1,20 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.clustercontroller.utils.staterestapi.server;
+
+import com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.InvalidContentException;
+import org.junit.Test;
+
+import java.time.Duration;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+
+public class JsonReaderTest {
+ @Test
+ public void testParsingOfTimeout() throws InvalidContentException {
+ assertEquals(Optional.empty(), JsonReader.parseTimeout(null));
+ assertEquals(Optional.of(Duration.ofMillis(12500)), JsonReader.parseTimeout("12.5"));
+ assertEquals(Optional.of(Duration.ofMillis(0)), JsonReader.parseTimeout("-1"));
+ assertEquals(Optional.of(Duration.ofMillis(0)), JsonReader.parseTimeout("0.0001"));
+ }
+} \ No newline at end of file