diff options
author | jonmv <venstad@gmail.com> | 2022-12-07 13:08:29 +0100 |
---|---|---|
committer | jonmv <venstad@gmail.com> | 2022-12-07 13:08:29 +0100 |
commit | 529f447bbeaf707a4976b8ec9c45491278ec4857 (patch) | |
tree | 71a91dfe51a08fdbd7b768bfe3e5d35fa00afe24 | |
parent | 304816b9d4876fe33c66cdd8da4f084d32c8df67 (diff) |
Store and display reindexing cause
20 files changed, 174 insertions, 108 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/Reindexing.java b/config-model-api/src/main/java/com/yahoo/config/model/api/Reindexing.java index 74b63a56ea6..b1164709bfc 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/Reindexing.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/Reindexing.java @@ -26,6 +26,9 @@ public interface Reindexing { /** The relative speed with which to reindex. */ double speed(); + /** The cause of reindexing for this document type. */ + String cause(); + } Reindexing DISABLED_INSTANCE = new Reindexing() {}; diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java index eb77187014f..155d81aabf9 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java @@ -544,5 +544,7 @@ public class ClusterControllerTestCase extends DomBuilderTest { @Override public boolean enabled() { return true; } @Override public Instant ready() { return Instant.EPOCH; } @Override public double speed() { return 1; } + @Override public String cause() { return "cause"; } + } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabase.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabase.java index 34fe8a2159d..438ac7dc9a8 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabase.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabase.java @@ -174,6 +174,7 @@ public class ApplicationCuratorDatabase { private static final String GENERATION = "generation"; private static final String EPOCH_MILLIS = "epochMillis"; private static final String SPEED = "speed"; + private static final String CAUSE = "cause"; private static byte[] toBytes(ApplicationReindexing reindexing) { Cursor root = new Slime().setObject(); @@ -204,6 +205,7 @@ public class ApplicationCuratorDatabase { private static void setStatus(Cursor statusObject, Status status) { statusObject.setLong(EPOCH_MILLIS, status.ready().toEpochMilli()); statusObject.setDouble(SPEED, status.speed()); + statusObject.setString(CAUSE, status.cause()); } private static ApplicationReindexing fromBytes(byte[] data) { @@ -225,7 +227,8 @@ public class ApplicationCuratorDatabase { private static Status getStatus(Inspector statusObject) { return new Status(Instant.ofEpochMilli(statusObject.field(EPOCH_MILLIS).asLong()), - statusObject.field(SPEED).valid() ? statusObject.field(SPEED).asDouble() : 0.2); + statusObject.field(SPEED).valid() ? statusObject.field(SPEED).asDouble() : 0.2, + statusObject.field(CAUSE).asString()); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationReindexing.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationReindexing.java index 19395b10b2b..f4e1918e6e3 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationReindexing.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/ApplicationReindexing.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.config.server.application; import com.yahoo.config.model.api.Reindexing; +import com.yahoo.vespa.config.server.maintenance.ReindexingMaintainer; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -37,10 +38,10 @@ public class ApplicationReindexing implements Reindexing { } /** Returns a copy of this with reindexing for the given document type in the given cluster ready at the given instant. */ - public ApplicationReindexing withReady(String cluster, String documentType, Instant readyAt, double speed) { + public ApplicationReindexing withReady(String cluster, String documentType, Instant readyAt, double speed, String cause) { Cluster current = clusters.getOrDefault(cluster, Cluster.empty()); Cluster modified = new Cluster(current.pending, - with(documentType, new Status(readyAt, speed), current.ready)); + with(documentType, new Status(readyAt, speed, cause), current.ready)); return new ApplicationReindexing(enabled, with(cluster, modified, clusters)); } @@ -172,13 +173,17 @@ public class ApplicationReindexing implements Reindexing { private final Instant ready; private final double speed; + private final String cause; - Status(Instant ready, double speed) { + Status(Instant ready, double speed, String cause) { if (speed <= 0 || 10 < speed) throw new IllegalArgumentException("Reindexing speed must be in (0, 10], but was " + speed); this.ready = ready.truncatedTo(ChronoUnit.MILLIS); this.speed = speed; + this.cause = cause.isBlank() ? speed < ReindexingMaintainer.SPEED ? "background reindexing, to account for changes in built-in linguistics components" + : "reindexing due to a schema change" + : cause; } @Override @@ -190,21 +195,26 @@ public class ApplicationReindexing implements Reindexing { } @Override + public String cause() { + return cause; + } + + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Status status = (Status) o; - return Double.compare(status.speed, speed) == 0 && ready.equals(status.ready); + return Double.compare(status.speed, speed) == 0 && ready.equals(status.ready) && cause.equals(status.cause); } @Override public int hashCode() { - return Objects.hash(ready, speed); + return Objects.hash(ready, speed, cause); } @Override public String toString() { - return "ready at " + ready + ", with relative speed " + speed; + return cause + ", ready at " + ready + ", with relative speed " + speed; } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java index 8afffd93a29..4d28b58beb3 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandler.java @@ -252,6 +252,7 @@ public class ApplicationHandler extends HttpHandler { Set<String> clusters = StringUtilities.split(request.getProperty("clusterId")); Set<String> types = StringUtilities.split(request.getProperty("documentType")); double speed = Double.parseDouble(Objects.requireNonNullElse(request.getProperty("speed"), "1")); + String cause = Objects.requireNonNullElse(request.getProperty("cause"), "reindexing for an unknown reason"); Map<String, Set<String>> reindexed = new TreeMap<>(); Instant now = applicationRepository.clock().instant(); @@ -267,7 +268,7 @@ public class ApplicationHandler extends HttpHandler { String.join(", ", documentTypes.get(cluster))); if ( ! indexedOnly || indexedDocumentTypes.get(cluster).contains(type)) { - reindexing = reindexing.withReady(cluster, type, now, speed); + reindexing = reindexing.withReady(cluster, type, now, speed, cause); reindexed.computeIfAbsent(cluster, __ -> new TreeSet<>()).add(type); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ReindexingResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ReindexingResponse.java index 1844b204a63..3ad09ea6345 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ReindexingResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/response/ReindexingResponse.java @@ -40,6 +40,7 @@ public class ReindexingResponse extends JSONResponse { private static void setStatus(Cursor object, ApplicationReindexing.Status readyStatus) { object.setLong("readyMillis", readyStatus.ready().toEpochMilli()); object.setDouble("speed", readyStatus.speed()); + object.setString("cause", readyStatus.cause()); } private static void setStatus(Cursor object, ClusterReindexing.Status status) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java index 99c3ecae62a..05f3f2c6483 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainer.java @@ -40,7 +40,8 @@ public class ReindexingMaintainer extends ConfigServerMaintainer { private static final Duration timeout = Duration.ofSeconds(10); /** Relative reindexing speed. */ - static final double SPEED = 1; + public static final double SPEED = 1; + static final String CAUSE = "reindexing due to a schema change"; private final ConfigConvergenceChecker convergence; private final Clock clock; @@ -96,7 +97,7 @@ public class ReindexingMaintainer extends ConfigServerMaintainer { for (var cluster : reindexing.clusters().entrySet()) for (var pending : cluster.getValue().pending().entrySet()) if (pending.getValue() <= oldestGeneration.get()) { - reindexing = reindexing.withReady(cluster.getKey(), pending.getKey(), now, SPEED) + reindexing = reindexing.withReady(cluster.getKey(), pending.getKey(), now, SPEED, CAUSE) .withoutPending(cluster.getKey(), pending.getKey()); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabaseTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabaseTest.java index eb66e7abd88..cbdb462c35e 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabaseTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationCuratorDatabaseTest.java @@ -9,6 +9,7 @@ import java.time.Instant; import java.util.Optional; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; /** * @author jonmv @@ -23,8 +24,11 @@ public class ApplicationCuratorDatabaseTest { assertEquals(Optional.empty(), db.readReindexingStatus(id)); ApplicationReindexing reindexing = ApplicationReindexing.empty() - .withPending("one", "a", 10).withReady("two", "b", Instant.ofEpochMilli(2), 0.2) - .withPending("two", "b", 20).withReady("one", "a", Instant.ofEpochMilli(1), 0.2).withReady("two", "c", Instant.ofEpochMilli(3), 0.2) + .withPending("one", "a", 10) + .withReady("two", "b", Instant.ofEpochMilli(2), 0.2, "test reindexing") + .withPending("two", "b", 20) + .withReady("one", "a", Instant.ofEpochMilli(1), 0.2, "test reindexing") + .withReady("two", "c", Instant.ofEpochMilli(3), 0.2, "test reindexing") .enabled(false); db.writeReindexingStatus(id, reindexing); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationReindexingTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationReindexingTest.java index 3a19cee6675..80ac28e9dbc 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationReindexingTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/ApplicationReindexingTest.java @@ -22,10 +22,10 @@ public class ApplicationReindexingTest { public void test() { ApplicationReindexing reindexing = ApplicationReindexing.empty() .withPending("one", "a", 10) - .withReady("two", "b", Instant.ofEpochMilli(2), 3) + .withReady("two", "b", Instant.ofEpochMilli(2), 3, "test reindexing") .withPending("two", "b", 20) - .withReady("one", "a", Instant.ofEpochMilli(1), 1) - .withReady("two", "a", Instant.ofEpochMilli(3), 2) + .withReady("one", "a", Instant.ofEpochMilli(1), 1, "test reindexing") + .withReady("two", "a", Instant.ofEpochMilli(3), 2, "test reindexing") .withoutPending("one", "a"); assertEquals(Instant.ofEpochMilli(1), @@ -51,14 +51,14 @@ public class ApplicationReindexingTest { assertEquals(Set.of("one", "two"), reindexing.clusters().keySet()); - assertEquals(Map.of("a", new Status(Instant.ofEpochMilli(1), 1)), + assertEquals(Map.of("a", new Status(Instant.ofEpochMilli(1), 1, "test reindexing")), reindexing.clusters().get("one").ready()); assertEquals(Map.of(), reindexing.clusters().get("one").pending()); - assertEquals(Map.of("a", new Status(Instant.ofEpochMilli(3), 2), - "b", new Status(Instant.ofEpochMilli(2), 3)), + assertEquals(Map.of("a", new Status(Instant.ofEpochMilli(3), 2, "test reindexing"), + "b", new Status(Instant.ofEpochMilli(2), 3, "test reindexing")), reindexing.clusters().get("two").ready()); assertEquals(Map.of("b", 20L), diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java index d543820fc68..b24d37f29fd 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java @@ -241,37 +241,48 @@ public class ApplicationHandlerTest { clock.advance(Duration.ofSeconds(1)); reindex(applicationId, "", "{\"message\":\"Reindexing document types [bar] in 'boo', [bar, bax, baz] in 'foo' of application default.default\"}"); - expected = expected.withReady("boo", "bar", clock.instant(), 1).withReady("foo", "bar", clock.instant(), 1).withReady("foo", "baz", clock.instant(), 1).withReady("foo", "bax", clock.instant(), 1); + expected = expected.withReady("boo", "bar", clock.instant(), 1, "reindexing for an unknown reason") + .withReady("foo", "bar", clock.instant(), 1, "reindexing for an unknown reason") + .withReady("foo", "baz", clock.instant(), 1, "reindexing for an unknown reason") + .withReady("foo", "bax", clock.instant(), 1, "reindexing for an unknown reason"); assertEquals(expected, database.readReindexingStatus(applicationId).orElseThrow()); clock.advance(Duration.ofSeconds(1)); - reindex(applicationId, "?indexedOnly=true", "{\"message\":\"Reindexing document types [bar] in 'foo' of application default.default\"}"); - expected = expected.withReady("foo", "bar", clock.instant(), 1); + reindex(applicationId, "?indexedOnly=true&cause=test%20reindexing", "{\"message\":\"Reindexing document types [bar] in 'foo' of application default.default\"}"); + expected = expected.withReady("foo", "bar", clock.instant(), 1, "test reindexing"); assertEquals(expected, database.readReindexingStatus(applicationId).orElseThrow()); clock.advance(Duration.ofSeconds(1)); - expected = expected.withReady("boo", "bar", clock.instant(), 1).withReady("foo", "bar", clock.instant(), 1).withReady("foo", "baz", clock.instant(), 1).withReady("foo", "bax", clock.instant(), 1); - reindex(applicationId, "?clusterId=", "{\"message\":\"Reindexing document types [bar] in 'boo', [bar, bax, baz] in 'foo' of application default.default\"}"); + expected = expected.withReady("boo", "bar", clock.instant(), 1, "reindexing") + .withReady("foo", "bar", clock.instant(), 1, "reindexing") + .withReady("foo", "baz", clock.instant(), 1, "reindexing") + .withReady("foo", "bax", clock.instant(), 1, "reindexing"); + reindex(applicationId, "?clusterId=&cause=reindexing", "{\"message\":\"Reindexing document types [bar] in 'boo', [bar, bax, baz] in 'foo' of application default.default\"}"); assertEquals(expected, database.readReindexingStatus(applicationId).orElseThrow()); clock.advance(Duration.ofSeconds(1)); - expected = expected.withReady("boo", "bar", clock.instant(), 1).withReady("foo", "bar", clock.instant(), 1); - reindex(applicationId, "?documentType=bar", "{\"message\":\"Reindexing document types [bar] in 'boo', [bar] in 'foo' of application default.default\"}"); + expected = expected.withReady("boo", "bar", clock.instant(), 1, "reindexing") + .withReady("foo", "bar", clock.instant(), 1, "reindexing"); + reindex(applicationId, "?documentType=bar&cause=reindexing", "{\"message\":\"Reindexing document types [bar] in 'boo', [bar] in 'foo' of application default.default\"}"); assertEquals(expected, database.readReindexingStatus(applicationId).orElseThrow()); clock.advance(Duration.ofSeconds(1)); - reindex(applicationId, "?clusterId=foo,boo", "{\"message\":\"Reindexing document types [bar] in 'boo', [bar, bax, baz] in 'foo' of application default.default\"}"); - expected = expected.withReady("boo", "bar", clock.instant(), 1).withReady("foo", "bar", clock.instant(), 1).withReady("foo", "baz", clock.instant(), 1).withReady("foo", "bax", clock.instant(), 1); + reindex(applicationId, "?clusterId=foo,boo&cause=reindexing", "{\"message\":\"Reindexing document types [bar] in 'boo', [bar, bax, baz] in 'foo' of application default.default\"}"); + expected = expected.withReady("boo", "bar", clock.instant(), 1, "reindexing") + .withReady("foo", "bar", clock.instant(), 1, "reindexing") + .withReady("foo", "baz", clock.instant(), 1, "reindexing") + .withReady("foo", "bax", clock.instant(), 1, "reindexing"); assertEquals(expected, database.readReindexingStatus(applicationId).orElseThrow()); clock.advance(Duration.ofSeconds(1)); - reindex(applicationId, "?clusterId=foo&documentType=bar,baz&speed=0.1", "{\"message\":\"Reindexing document types [bar, baz] in 'foo' of application default.default\"}"); - expected = expected.withReady("foo", "bar", clock.instant(), 0.1).withReady("foo", "baz", clock.instant(), 0.1); + reindex(applicationId, "?clusterId=foo&documentType=bar,baz&speed=0.1&cause=reindexing", "{\"message\":\"Reindexing document types [bar, baz] in 'foo' of application default.default\"}"); + expected = expected.withReady("foo", "bar", clock.instant(), 0.1, "reindexing") + .withReady("foo", "baz", clock.instant(), 0.1, "reindexing"); assertEquals(expected, database.readReindexingStatus(applicationId).orElseThrow()); @@ -298,7 +309,8 @@ public class ApplicationHandlerTest { " \"ready\": {" + " \"bar\": {" + " \"readyMillis\": " + (now - 1000) + ", " + - " \"speed\": 1.0" + + " \"speed\": 1.0," + + " \"cause\": \"reindexing\"" + " }" + " }" + " }," + @@ -307,15 +319,18 @@ public class ApplicationHandlerTest { " \"ready\": {" + " \"bar\": {" + " \"readyMillis\": " + now + ", " + - " \"speed\": 0.1" + + " \"speed\": 0.1," + + " \"cause\": \"reindexing\"" + " }," + " \"bax\": {" + " \"readyMillis\": " + (now - 1000) + ", " + - " \"speed\": 1.0" + + " \"speed\": 1.0," + + " \"cause\": \"reindexing\"" + " }," + " \"baz\": {" + " \"readyMillis\": " + now + ", " + - " \"speed\": 0.1" + + " \"speed\": 0.1," + + " \"cause\": \"reindexing\"" + " }" + " }" + " }" + @@ -499,7 +514,7 @@ public class ApplicationHandlerTest { public void testReindexingSerialization() throws IOException { Instant now = Instant.ofEpochMilli(123456); ApplicationReindexing applicationReindexing = ApplicationReindexing.empty() - .withPending("foo", "bar", 123L).withReady("moo", "baz", now, 1); + .withPending("foo", "bar", 123L).withReady("moo", "baz", now, 1, "reindexing"); ClusterReindexing clusterReindexing = new ClusterReindexing(Map.of("bax", new Status(now, null, null, null, null), "baz", new Status(now.plusSeconds(1), now.plusSeconds(2), @@ -514,53 +529,56 @@ public class ApplicationHandlerTest { applicationReindexing, Map.of("boo", clusterReindexing, "moo", clusterReindexing))), - "{\n" + - " \"enabled\": true,\n" + - " \"clusters\": {\n" + - " \"boo\": {\n" + - " \"pending\": {},\n" + - " \"ready\": {\n" + - " \"bar\": {},\n" + - " \"bax\": {\n" + - " \"startedMillis\": 123456\n" + - " },\n" + - " \"baz\": {\n" + - " \"startedMillis\": 124456,\n" + - " \"endedMillis\": 125456,\n" + - " \"state\": \"failed\",\n" + - " \"message\": \"message\",\n" + - " \"progress\": 0.1\n" + - " }\n" + - " }\n" + - " },\n" + - " \"foo\": {\n" + - " \"pending\": {\n" + - " \"bar\": 123\n" + - " },\n" + - " \"ready\": {\n" + - " \"bar\": {},\n" + - " \"hax\": {}\n" + - " }\n" + - " },\n" + - " \"moo\": {\n" + - " \"pending\": {},\n" + - " \"ready\": {\n" + - " \"bax\": {\n" + - " \"startedMillis\": 123456\n" + - " },\n" + - " \"baz\": {\n" + - " \"readyMillis\": 123456,\n" + - " \"speed\": 1.0,\n" + - " \"startedMillis\": 124456,\n" + - " \"endedMillis\": 125456,\n" + - " \"state\": \"failed\",\n" + - " \"message\": \"message\",\n" + - " \"progress\": 0.1\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - "}\n"); + """ + { + "enabled": true, + "clusters": { + "boo": { + "pending": {}, + "ready": { + "bar": {}, + "bax": { + "startedMillis": 123456 + }, + "baz": { + "startedMillis": 124456, + "endedMillis": 125456, + "state": "failed", + "message": "message", + "progress": 0.1 + } + } + }, + "foo": { + "pending": { + "bar": 123 + }, + "ready": { + "bar": {}, + "hax": {} + } + }, + "moo": { + "pending": {}, + "ready": { + "bax": { + "startedMillis": 123456 + }, + "baz": { + "readyMillis": 123456, + "speed": 1.0, + "cause": "reindexing", + "startedMillis": 124456, + "endedMillis": 125456, + "state": "failed", + "message": "message", + "progress": 0.1 + } + } + } + } + } + """); } @Test diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainerTest.java index 26edc5d0f71..5a78d81e508 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/maintenance/ReindexingMaintainerTest.java @@ -8,6 +8,7 @@ import java.time.Instant; import java.util.List; import java.util.Map; +import static com.yahoo.vespa.config.server.maintenance.ReindexingMaintainer.CAUSE; import static com.yahoo.vespa.config.server.maintenance.ReindexingMaintainer.SPEED; import static com.yahoo.vespa.config.server.maintenance.ReindexingMaintainer.withNewReady; import static com.yahoo.vespa.config.server.maintenance.ReindexingMaintainer.withOnlyCurrentData; @@ -22,7 +23,10 @@ public class ReindexingMaintainerTest { public void testReadyComputation() { ApplicationReindexing reindexing = ApplicationReindexing.empty() .withPending("one", "a", 10) - .withPending("two", "b", 20).withReady("one", "a", Instant.ofEpochMilli(3), SPEED).withReady("two", "b", Instant.ofEpochMilli(2), SPEED).withReady("two", "c", Instant.ofEpochMilli(3), SPEED); + .withPending("two", "b", 20) + .withReady("one", "a", Instant.ofEpochMilli(3), SPEED, CAUSE) + .withReady("two", "b", Instant.ofEpochMilli(2), SPEED, CAUSE) + .withReady("two", "c", Instant.ofEpochMilli(3), SPEED, CAUSE); // Nothing happens without convergence. assertEquals(reindexing, @@ -31,13 +35,13 @@ public class ReindexingMaintainerTest { // Status for (one, a) changes, but not (two, b). Instant later = Instant.ofEpochMilli(3 << 10); // Converged, no longer pending. - assertEquals(reindexing.withoutPending("one", "a").withReady("one", "a", later, SPEED), // Converged, now ready. + assertEquals(reindexing.withoutPending("one", "a").withReady("one", "a", later, SPEED, CAUSE), // Converged, now ready. withNewReady(reindexing, () -> 19L, later)); // Converged, no longer pending. // Converged, no Longer pending. - assertEquals(reindexing.withoutPending("one", "a").withReady("one", "a", later, SPEED) - .withoutPending("two", "b").withReady("two", "b", later, SPEED), + assertEquals(reindexing.withoutPending("one", "a").withReady("one", "a", later, SPEED, CAUSE) + .withoutPending("two", "b").withReady("two", "b", later, SPEED, CAUSE), withNewReady(reindexing, () -> 20L, later)); // Verify generation supplier isn't called when no pending document types. @@ -50,7 +54,10 @@ public class ReindexingMaintainerTest { public void testGarbageRemoval() { ApplicationReindexing reindexing = ApplicationReindexing.empty() .withPending("one", "a", 10) - .withPending("two", "b", 20).withReady("one", "a", Instant.ofEpochMilli(3), SPEED).withReady("two", "b", Instant.ofEpochMilli(2), SPEED).withReady("two", "c", Instant.ofEpochMilli(3), SPEED); + .withPending("two", "b", 20) + .withReady("one", "a", Instant.ofEpochMilli(3), SPEED, CAUSE) + .withReady("two", "b", Instant.ofEpochMilli(2), SPEED, CAUSE) + .withReady("two", "c", Instant.ofEpochMilli(3), SPEED, CAUSE); assertEquals(reindexing, withOnlyCurrentData(reindexing, Map.of("one", List.of("a", "b", "c", "d"), @@ -62,10 +69,13 @@ public class ReindexingMaintainerTest { "two", List.of("b", "c")))); assertEquals(ApplicationReindexing.empty() - .withPending("two", "b", 20).withReady("two", "b", Instant.ofEpochMilli(2), SPEED), + .withPending("two", "b", 20).withReady("two", "b", Instant.ofEpochMilli(2), SPEED, CAUSE), withOnlyCurrentData(reindexing, Map.of("two", List.of("a", "b")))); - assertEquals(ApplicationReindexing.empty().withReady("one", "a", Instant.EPOCH, SPEED).without("one", "a").withReady("two", "c", Instant.ofEpochMilli(3), SPEED), + assertEquals(ApplicationReindexing.empty() + .withReady("one", "a", Instant.EPOCH, SPEED, CAUSE) + .without("one", "a") + .withReady("two", "c", Instant.ofEpochMilli(3), SPEED, CAUSE), withOnlyCurrentData(reindexing, Map.of("one", List.of("c"), "two", List.of("c")))); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ApplicationReindexing.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ApplicationReindexing.java index 305cd4c802e..d1ecae63f79 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ApplicationReindexing.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ApplicationReindexing.java @@ -87,7 +87,7 @@ public class ApplicationReindexing { @Override public String toString() { return "Cluster{" + - ", pending=" + pending + + "pending=" + pending + ", ready=" + ready + '}'; } @@ -104,8 +104,9 @@ public class ApplicationReindexing { private final String message; private final Double progress; private final Double speed; + private final String cause; - public Status(Instant readyAt, Instant startedAt, Instant endedAt, State state, String message, Double progress, Double speed) { + public Status(Instant readyAt, Instant startedAt, Instant endedAt, State state, String message, Double progress, Double speed, String cause) { this.readyAt = readyAt; this.startedAt = startedAt; this.endedAt = endedAt; @@ -113,10 +114,11 @@ public class ApplicationReindexing { this.message = message; this.progress = progress; this.speed = speed; + this.cause = cause; } public Status(Instant readyAt) { - this(readyAt, null, null, null, null, null, 1.0); + this(readyAt, null, null, null, null, null, 1.0, null); } public Optional<Instant> readyAt() { return Optional.ofNullable(readyAt); } @@ -126,18 +128,26 @@ public class ApplicationReindexing { public Optional<String> message() { return Optional.ofNullable(message); } public Optional<Double> progress() { return Optional.ofNullable(progress); } public Optional<Double> speed() { return Optional.ofNullable(speed); } + public Optional<String> cause() { return Optional.ofNullable(cause); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Status status = (Status) o; - return Objects.equals(readyAt, status.readyAt) && Objects.equals(startedAt, status.startedAt) && Objects.equals(endedAt, status.endedAt) && state == status.state && Objects.equals(message, status.message) && Objects.equals(progress, status.progress) && Objects.equals(speed, status.speed); + return Objects.equals(readyAt, status.readyAt) && + Objects.equals(startedAt, status.startedAt) && + Objects.equals(endedAt, status.endedAt) && + state == status.state && + Objects.equals(message, status.message) && + Objects.equals(progress, status.progress) && + Objects.equals(speed, status.speed) && + Objects.equals(cause, status.cause); } @Override public int hashCode() { - return Objects.hash(readyAt, startedAt, endedAt, state, message, progress, speed); + return Objects.hash(readyAt, startedAt, endedAt, state, message, progress, speed, cause); } @Override @@ -150,6 +160,7 @@ public class ApplicationReindexing { ", message='" + message + '\'' + ", progress=" + progress + ", speed=" + speed + + ", cause='" + cause + '\'' + '}'; } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServer.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServer.java index 119e6794e6c..cc05bc01d99 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServer.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/ConfigServer.java @@ -38,7 +38,7 @@ public interface ConfigServer { PreparedApplication deploy(DeploymentData deployment); - void reindex(DeploymentId deployment, List<String> clusterNames, List<String> documentTypes, boolean indexedOnly, Double speed); + void reindex(DeploymentId deployment, List<String> clusterNames, List<String> documentTypes, boolean indexedOnly, Double speed, String cause); ApplicationReindexing getReindexing(DeploymentId deployment); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java index 602a53035a6..444a0ea5ac1 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java @@ -210,13 +210,13 @@ public class ApplicationController { /** * Triggers reindexing for the given document types in the given clusters, for the given application. - * + * <p> * If no clusters are given, reindexing is triggered for the entire application; otherwise * if no documents types are given, reindexing is triggered for all given clusters; otherwise * reindexing is triggered for the cartesian product of the given clusters and document types. */ - public void reindex(ApplicationId id, ZoneId zoneId, List<String> clusterNames, List<String> documentTypes, boolean indexedOnly, Double speed) { - configServer.reindex(new DeploymentId(id, zoneId), clusterNames, documentTypes, indexedOnly, speed); + public void reindex(ApplicationId id, ZoneId zoneId, List<String> clusterNames, List<String> documentTypes, boolean indexedOnly, Double speed, String cause) { + configServer.reindex(new DeploymentId(id, zoneId), clusterNames, documentTypes, indexedOnly, speed, cause); } /** Returns the reindexing status for the given application in the given zone. */ diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java index 1ee13bbd0c0..400673bfd0c 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggerer.java @@ -50,7 +50,8 @@ public class ReindexingTriggerer extends ControllerMaintainer { for (Deployment deployment : deployments) if ( inWindowOfOpportunity(now, id, deployment.zone()) && reindexingIsReady(controller().applications().applicationReindexing(id, deployment.zone()), now)) - controller().applications().reindex(id, deployment.zone(), List.of(), List.of(), true, speed); + controller().applications().reindex(id, deployment.zone(), List.of(), List.of(), true, speed, + "bakground reindexing, to account for changes in built-in linguistics components"); }); return 1.0; } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index 001c0b8e522..a10f79d1727 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -2229,7 +2229,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler { Double speed = request.hasProperty("speed") ? Double.parseDouble(request.getProperty("speed")) : null; boolean indexedOnly = request.getBooleanProperty("indexedOnly"); - controller.applications().reindex(id, zone, clusterNames, documentTypes, indexedOnly, speed); + controller.applications().reindex(id, zone, clusterNames, documentTypes, indexedOnly, speed, "reindexing triggered by " + requireUserPrincipal(request).getName()); return new MessageResponse("Requested reindexing of " + id + " in " + zone + (clusterNames.isEmpty() ? "" : ", on clusters " + String.join(", ", clusterNames)) + (documentTypes.isEmpty() ? "" : ", for types " + String.join(", ", documentTypes)) + @@ -2281,6 +2281,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler { status.message().ifPresent(message -> statusObject.setString("message", message)); status.progress().ifPresent(progress -> statusObject.setDouble("progress", progress)); status.speed().ifPresent(speed -> statusObject.setDouble("speed", speed)); + status.cause().ifPresent(cause -> statusObject.setString("cause", cause)); } private static String toString(ApplicationReindexing.State state) { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java index c76ed8e8c46..21f76ac4303 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java @@ -440,7 +440,7 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer } @Override - public void reindex(DeploymentId deployment, List<String> clusterNames, List<String> documentTypes, boolean indexedOnly, Double speed) { } + public void reindex(DeploymentId deployment, List<String> clusterNames, List<String> documentTypes, boolean indexedOnly, Double speed, String cause) { } @Override public ApplicationReindexing getReindexing(DeploymentId deployment) { @@ -453,7 +453,8 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer ApplicationReindexing.State.FAILED, "(#`д´)ノ", 0.1, - 1.0))))); + 1.0, + "test reindexing"))))); } @Override diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java index b0601dcd880..ecb5bf167d0 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ReindexingTriggererTest.java @@ -68,7 +68,7 @@ public class ReindexingTriggererTest { Map.of("cluster", new Cluster(Map.of(), Map.of("type", - new Status(then, then, null, null, null, null, 1.0))))); + new Status(then, then, null, null, null, null, 1.0, null))))); assertFalse(reindexingIsReady(reindexing, now), "Should not be ready when reindexing is already running"); @@ -76,7 +76,7 @@ public class ReindexingTriggererTest { Map.of("cluster", new Cluster(Map.of("type", 123L), Map.of("type", - new Status(then, then, now, null, null, null, 1.0))))); + new Status(then, then, now, null, null, null, 1.0, null))))); assertTrue(reindexingIsReady(reindexing, now), "Should be ready when reindexing is no longer running"); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index 40d96f716ae..f1381ead221 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -630,7 +630,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // GET to get reindexing status tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/reindexing", GET) .userIdentity(USER_ID), - "{\"enabled\":true,\"clusters\":[{\"name\":\"cluster\",\"pending\":[{\"type\":\"type\",\"requiredGeneration\":100}],\"ready\":[{\"type\":\"type\",\"readyAtMillis\":345,\"startedAtMillis\":456,\"endedAtMillis\":567,\"state\":\"failed\",\"message\":\"(#`д´)ノ\",\"progress\":0.1,\"speed\":1.0}]}]}"); + "{\"enabled\":true,\"clusters\":[{\"name\":\"cluster\",\"pending\":[{\"type\":\"type\",\"requiredGeneration\":100}],\"ready\":[{\"type\":\"type\",\"readyAtMillis\":345,\"startedAtMillis\":456,\"endedAtMillis\":567,\"state\":\"failed\",\"message\":\"(#`д´)ノ\",\"progress\":0.1,\"speed\":1.0,\"cause\":\"test reindexing\"}]}]}"); // POST to request a service dump tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/node/host-tenant1.application1.instance1-prod.us-central-1/service-dump", POST) diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java index 06cdccd17fc..10040ab6d0f 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java @@ -1110,10 +1110,9 @@ public class DocumentV1ApiHandler extends AbstractRequestHandler { private void updateRemoveMetrics(Outcome outcome) { switch (outcome) { - case SUCCESS: - case NOT_FOUND: metric.add(MetricNames.SUCCEEDED, 1, null); break; - case CONDITION_FAILED: metric.add(MetricNames.CONDITION_NOT_MET, 1, null); break; - default: metric.add(MetricNames.FAILED, 1, null); break; + case SUCCESS, NOT_FOUND -> metric.add(MetricNames.SUCCEEDED, 1, null); + case CONDITION_FAILED -> metric.add(MetricNames.CONDITION_NOT_MET, 1, null); + case INSUFFICIENT_STORAGE, TIMEOUT, ERROR -> metric.add(MetricNames.FAILED, 1, null); } } |