summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Marius Venstad <venstad@gmail.com>2021-05-21 13:51:39 +0200
committerJon Marius Venstad <venstad@gmail.com>2021-05-21 13:51:39 +0200
commit5783df40a392b2c5d365bef8e5fd9cd1a717e2fb (patch)
treecf18ac66870d092a096079b1f382dd75cbc134e8
parent0ab97739be414a7d26951f5fbb9daba7cbccd5fa (diff)
Cache badges for 1 minute
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiHandler.java85
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java14
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg177
-rw-r--r--document/src/main/java/com/yahoo/document/DataType.java2
6 files changed, 266 insertions, 17 deletions
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java
index 27a32f3e754..f9ccdb1a2aa 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/DocumentDatabaseChangeValidatorTest.java
@@ -2,7 +2,6 @@
package com.yahoo.vespa.model.application.validation.change.search;
import com.yahoo.config.application.api.ValidationId;
-import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.vespa.model.application.validation.change.VespaConfigChangeAction;
import org.junit.Test;
@@ -11,9 +10,9 @@ import java.time.Instant;
import java.util.Arrays;
import java.util.List;
+import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRefeedAction;
import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newReindexAction;
import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRestartAction;
-import static com.yahoo.vespa.model.application.validation.change.ConfigChangeTestUtils.newRefeedAction;
public class DocumentDatabaseChangeValidatorTest {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiHandler.java
index ff24253128b..e2922c040d2 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiHandler.java
@@ -18,7 +18,12 @@ import com.yahoo.yolean.Exceptions;
import java.io.IOException;
import java.io.OutputStream;
+import java.time.Instant;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
+import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -35,6 +40,7 @@ public class BadgeApiHandler extends LoggingRequestHandler {
private final static Logger log = Logger.getLogger(BadgeApiHandler.class.getName());
private final Controller controller;
+ private final Map<Key, Value> badgeCache = new ConcurrentHashMap<>();
public BadgeApiHandler(Context parentCtx, Controller controller) {
super(parentCtx);
@@ -59,29 +65,44 @@ public class BadgeApiHandler extends LoggingRequestHandler {
private HttpResponse get(HttpRequest request) {
Path path = new Path(request.getUri());
- if (path.matches("/badge/v1/{tenant}/{application}/{instance}")) return badge(path.get("tenant"), path.get("application"), path.get("instance"));
- if (path.matches("/badge/v1/{tenant}/{application}/{instance}/{jobName}")) return badge(path.get("tenant"), path.get("application"), path.get("instance"), path.get("jobName"), request.getProperty("historyLength"));
+ if (path.matches("/badge/v1/{tenant}/{application}/{instance}")) return overviewBadge(path.get("tenant"), path.get("application"), path.get("instance"));
+ if (path.matches("/badge/v1/{tenant}/{application}/{instance}/{jobName}")) return historyBadge(path.get("tenant"), path.get("application"), path.get("instance"), path.get("jobName"), request.getProperty("historyLength"));
return ErrorResponse.notFoundError(String.format("No '%s' handler at '%s'", request.getMethod(),
request.getUri().getPath()));
}
/** Returns a URI which points to an overview badge for the given application. */
- private HttpResponse badge(String tenant, String application, String instance) {
+ private HttpResponse overviewBadge(String tenant, String application, String instance) {
ApplicationId id = ApplicationId.from(tenant, application, instance);
- DeploymentStatus status = controller.jobController().deploymentStatus(controller.applications().requireApplication(TenantAndApplicationId.from(id)));
- Predicate<JobStatus> isDeclaredJob = job -> status.jobSteps().get(job.id()) != null && status.jobSteps().get(job.id()).isDeclared();
- return svgResponse(Badges.overviewBadge(id,
- status.jobs().instance(id.instance()).matching(isDeclaredJob),
- controller.system()));
+ return cachedResponse(new Key(id, null, 0),
+ controller.clock().instant(),
+ () -> {
+ DeploymentStatus status = controller.jobController().deploymentStatus(controller.applications().requireApplication(TenantAndApplicationId.from(id)));
+ Predicate<JobStatus> isDeclaredJob = job -> status.jobSteps().get(job.id()) != null && status.jobSteps().get(job.id()).isDeclared();
+ return Badges.overviewBadge(id,
+ status.jobs().instance(id.instance()).matching(isDeclaredJob),
+ controller.system());
+ });
}
/** Returns a URI which points to a history badge for the given application and job type. */
- private HttpResponse badge(String tenant, String application, String instance, String jobName, String historyLength) {
+ private HttpResponse historyBadge(String tenant, String application, String instance, String jobName, String historyLength) {
ApplicationId id = ApplicationId.from(tenant, application, instance);
- return svgResponse(Badges.historyBadge(id,
- controller.jobController().jobStatus(new JobId(id, JobType.fromJobName(jobName))),
- historyLength == null ? 5 : Math.min(32, Math.max(0, Integer.parseInt(historyLength)))));
+ JobType type = JobType.fromJobName(jobName);
+ int length = historyLength == null ? 5 : Math.min(32, Math.max(0, Integer.parseInt(historyLength)));
+ return cachedResponse(new Key(id, type, length),
+ controller.clock().instant(),
+ () -> Badges.historyBadge(id,
+ controller.jobController().jobStatus(new JobId(id, type)),
+ length)
+ );
+ }
+
+ private HttpResponse cachedResponse(Key key, Instant now, Supplier<String> badge) {
+ return svgResponse(badgeCache.compute(key, (__, value) -> {
+ return value != null && value.expiry.isAfter(now) ? value : new Value(badge.get(), now);
+ }).badgeSvg);
}
private static HttpResponse svgResponse(String svg) {
@@ -95,4 +116,44 @@ public class BadgeApiHandler extends LoggingRequestHandler {
};
}
+
+ private static class Key {
+
+ private final ApplicationId id;
+ private final JobType type;
+ private final int historyLength;
+
+ private Key(ApplicationId id, JobType type, int historyLength) {
+ this.id = id;
+ this.type = type;
+ this.historyLength = historyLength;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Key key = (Key) o;
+ return historyLength == key.historyLength && id.equals(key.id) && type == key.type;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, type, historyLength);
+ }
+
+ }
+
+ private static class Value {
+
+ private final String badgeSvg;
+ private final Instant expiry;
+
+ private Value(String badgeSvg, Instant created) {
+ this.badgeSvg = badgeSvg;
+ this.expiry = created.plusSeconds(60);
+ }
+
+ }
+
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java
index ebde4671859..766a84ca33c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java
@@ -13,6 +13,7 @@ import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.time.Duration;
/**
* @author jonmv
@@ -45,7 +46,7 @@ public class BadgeApiTest extends ControllerContainerTest {
application.submit(applicationPackage)
.runJob(JobType.systemTest)
.runJob(JobType.stagingTest);
- for (int i = 0; i < 32; i++)
+ for (int i = 0; i < 31; i++)
application.failDeployment(JobType.productionUsWest1);
application.triggerJobs();
tester.controller().applications().deploymentTrigger().reTrigger(application.instanceId(), JobType.testEuWest1);
@@ -54,6 +55,17 @@ public class BadgeApiTest extends ControllerContainerTest {
Files.readString(Paths.get(responseFiles + "overview.svg")), 200);
tester.assertResponse(authenticatedRequest("http://localhost:8080/badge/v1/tenant/application/default/production-us-west-1?historyLength=32"),
Files.readString(Paths.get(responseFiles + "history.svg")), 200);
+
+ // New change not reflected before cache entry expires.
+ tester.serviceRegistry().clock().advance(Duration.ofSeconds(59));
+ application.runJob(JobType.productionUsWest1);
+ tester.assertResponse(authenticatedRequest("http://localhost:8080/badge/v1/tenant/application/default/production-us-west-1?historyLength=32"),
+ Files.readString(Paths.get(responseFiles + "history.svg")), 200);
+
+ // Cached entry refreshed after a minute.
+ tester.serviceRegistry().clock().advance(Duration.ofSeconds(1));
+ tester.assertResponse(authenticatedRequest("http://localhost:8080/badge/v1/tenant/application/default/production-us-west-1?historyLength=32"),
+ Files.readString(Paths.get(responseFiles + "history2.svg")), 200);
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg
index f466f38750c..0e30796bae2 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg
@@ -47,7 +47,7 @@
<rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='#00f244'/>
<rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='url(#shade)'/>
<rect x='646.4043039211865' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='#bf103c'/>
+ <rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='#00f244'/>
<rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='url(#shade)'/>
<rect x='639.3307808029524' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='#bf103c'/>
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg
new file mode 100644
index 00000000000..46797ee534d
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg
@@ -0,0 +1,177 @@
+<svg xmlns='http://www.w3.org/2000/svg' width='659.058159125822' height='20' role='img' aria-label='Deployment Status'>
+ <title>Deployment Status</title>
+ <linearGradient id='light' x2='0' y2='100%'>
+ <stop offset='0' stop-color='#fff' stop-opacity='.5'/>
+ <stop offset='.1' stop-color='#fff' stop-opacity='.15'/>
+ <stop offset='.9' stop-color='#000' stop-opacity='.15'/>
+ <stop offset='1' stop-color='#000' stop-opacity='.5'/>
+ </linearGradient>
+ <linearGradient id='left-light' x2='100%' y2='0'>
+ <stop offset='0' stop-color='#fff' stop-opacity='.3'/>
+ <stop offset='.5' stop-color='#fff' stop-opacity='.1'/>
+ <stop offset='1' stop-color='#fff' stop-opacity='.0'/>
+ </linearGradient>
+ <linearGradient id='right-shadow' x2='100%' y2='0'>
+ <stop offset='0' stop-color='#000' stop-opacity='.0'/>
+ <stop offset='.5' stop-color='#000' stop-opacity='.1'/>
+ <stop offset='1' stop-color='#000' stop-opacity='.3'/>
+ </linearGradient>
+ <linearGradient id='shadow' x2='100%' y2='0'>
+ <stop offset='0' stop-color='#222' stop-opacity='.3'/>
+ <stop offset='.625' stop-color='#555' stop-opacity='.3'/>
+ <stop offset='.9' stop-color='#555' stop-opacity='.05'/>
+ <stop offset='1' stop-color='#555' stop-opacity='.0'/>
+ </linearGradient>
+ <linearGradient id='shade' x2='100%' y2='0'>
+ <stop offset='0' stop-color='#000' stop-opacity='.20'/>
+ <stop offset='0.05' stop-color='#000' stop-opacity='.10'/>
+ <stop offset='1' stop-color='#000' stop-opacity='.0'/>
+ </linearGradient>
+ <linearGradient id='run-on-failure' x1='40%' x2='80%' y2='0%'>
+ <stop offset='0' stop-color='#ab83ff' />
+ <stop offset='1' stop-color='#bf103c' />
+ <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
+ <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
+ </linearGradient>
+ <linearGradient id='run-on-success' x1='40%' x2='80%' y2='0%'>
+ <stop offset='0' stop-color='#ab83ff' />
+ <stop offset='1' stop-color='#00f244' />
+ <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
+ <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
+ </linearGradient>
+ <clipPath id='rounded'>
+ <rect width='659.058159125822' height='20' rx='3' fill='#fff'/>
+ </clipPath>
+ <g clip-path='url(#rounded)'>
+ <rect x='653.26809109179' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='#bf103c'/>
+ <rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='url(#shade)'/>
+ <rect x='646.4043039211865' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='#bf103c'/>
+ <rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='url(#shade)'/>
+ <rect x='639.3307808029524' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='#bf103c'/>
+ <rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='url(#shade)'/>
+ <rect x='632.0411128600877' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='624.2919036955889' rx='3' width='13.749209164498811' height='20' fill='#bf103c'/>
+ <rect x='624.2919036955889' rx='3' width='13.749209164498811' height='20' fill='url(#shade)'/>
+ <rect x='624.5286953802824' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='616.5426945310901' rx='3' width='13.986000849192376' height='20' fill='#bf103c'/>
+ <rect x='616.5426945310901' rx='3' width='13.986000849192376' height='20' fill='url(#shade)'/>
+ <rect x='616.7867218317995' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='608.5566936818977' rx='3' width='14.230028149901685' height='20' fill='#bf103c'/>
+ <rect x='608.5566936818977' rx='3' width='14.230028149901685' height='20' fill='url(#shade)'/>
+ <rect x='608.8081776965013' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='600.326665531996' rx='3' width='14.48151216450522' height='20' fill='#bf103c'/>
+ <rect x='600.326665531996' rx='3' width='14.48151216450522' height='20' fill='url(#shade)'/>
+ <rect x='600.5858341144344' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='591.8451533674908' rx='3' width='14.740680746943664' height='20' fill='#bf103c'/>
+ <rect x='591.8451533674908' rx='3' width='14.740680746943664' height='20' fill='url(#shade)'/>
+ <rect x='592.1122413342111' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='583.1044726205471' rx='3' width='15.007768713664104' height='20' fill='#bf103c'/>
+ <rect x='583.1044726205471' rx='3' width='15.007768713664104' height='20' fill='url(#shade)'/>
+ <rect x='583.3797219632555' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='574.096703906883' rx='3' width='15.283018056372542' height='20' fill='#bf103c'/>
+ <rect x='574.096703906883' rx='3' width='15.283018056372542' height='20' fill='url(#shade)'/>
+ <rect x='574.380364011798' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='564.8136858505105' rx='3' width='15.566678161287442' height='20' fill='#bf103c'/>
+ <rect x='564.8136858505105' rx='3' width='15.566678161287442' height='20' fill='url(#shade)'/>
+ <rect x='565.1060137243161' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='555.2470076892231' rx='3' width='15.859006035092985' height='20' fill='#bf103c'/>
+ <rect x='555.2470076892231' rx='3' width='15.859006035092985' height='20' fill='url(#shade)'/>
+ <rect x='555.5482681919269' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='545.3880016541301' rx='3' width='16.16026653779677' height='20' fill='#bf103c'/>
+ <rect x='545.3880016541301' rx='3' width='16.16026653779677' height='20' fill='url(#shade)'/>
+ <rect x='545.6984677390362' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='535.2277351163333' rx='3' width='16.470732622702883' height='20' fill='#bf103c'/>
+ <rect x='535.2277351163333' rx='3' width='16.470732622702883' height='20' fill='url(#shade)'/>
+ <rect x='535.5476880773482' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='524.7570024936304' rx='3' width='16.790685583717845' height='20' fill='#bf103c'/>
+ <rect x='524.7570024936304' rx='3' width='16.790685583717845' height='20' fill='url(#shade)'/>
+ <rect x='525.0867322201259' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='513.9663169099125' rx='3' width='17.12041531021341' height='20' fill='#bf103c'/>
+ <rect x='513.9663169099125' rx='3' width='17.12041531021341' height='20' fill='url(#shade)'/>
+ <rect x='514.3061221493763' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='502.84590159969906' rx='3' width='17.460220549677203' height='20' fill='#bf103c'/>
+ <rect x='502.84590159969906' rx='3' width='17.460220549677203' height='20' fill='url(#shade)'/>
+ <rect x='503.196090228411' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='491.38568105002184' rx='3' width='17.810409178389147' height='20' fill='#bf103c'/>
+ <rect x='491.38568105002184' rx='3' width='17.810409178389147' height='20' fill='url(#shade)'/>
+ <rect x='491.7465703520016' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='479.5752718716327' rx='3' width='18.171298480368904' height='20' fill='#bf103c'/>
+ <rect x='479.5752718716327' rx='3' width='18.171298480368904' height='20' fill='url(#shade)'/>
+ <rect x='479.9471888261109' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='467.40397339126383' rx='3' width='18.543215434847077' height='20' fill='#bf103c'/>
+ <rect x='467.40397339126383' rx='3' width='18.543215434847077' height='20' fill='url(#shade)'/>
+ <rect x='467.7872549689374' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='454.86075795641676' rx='3' width='18.92649701252067' height='20' fill='#bf103c'/>
+ <rect x='454.86075795641676' rx='3' width='18.92649701252067' height='20' fill='url(#shade)'/>
+ <rect x='455.25575142475725' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='441.9342609438961' rx='3' width='19.32149048086113' height='20' fill='#bf103c'/>
+ <rect x='441.9342609438961' rx='3' width='19.32149048086113' height='20' fill='url(#shade)'/>
+ <rect x='442.3413241817867' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='428.61277046303496' rx='3' width='19.728553718751726' height='20' fill='#bf103c'/>
+ <rect x='428.61277046303496' rx='3' width='19.728553718751726' height='20' fill='url(#shade)'/>
+ <rect x='429.03227228502243' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='414.8842167442832' rx='3' width='20.148055540739207' height='20' fill='#bf103c'/>
+ <rect x='414.8842167442832' rx='3' width='20.148055540739207' height='20' fill='url(#shade)'/>
+ <rect x='415.31653723473755' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='400.736161203544' rx='3' width='20.58037603119359' height='20' fill='#bf103c'/>
+ <rect x='400.736161203544' rx='3' width='20.58037603119359' height='20' fill='url(#shade)'/>
+ <rect x='401.1816920610293' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='386.1557851723504' rx='3' width='21.025906888678875' height='20' fill='#bf103c'/>
+ <rect x='386.1557851723504' rx='3' width='21.025906888678875' height='20' fill='url(#shade)'/>
+ <rect x='386.61493006451815' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='371.12987828367153' rx='3' width='21.485051780846597' height='20' fill='#bf103c'/>
+ <rect x='371.12987828367153' rx='3' width='21.485051780846597' height='20' fill='url(#shade)'/>
+ <rect x='371.60305321299876' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='355.6448265028249' rx='3' width='21.958226710173836' height='20' fill='#bf103c'/>
+ <rect x='355.6448265028249' rx='3' width='21.958226710173836' height='20' fill='url(#shade)'/>
+ <rect x='356.13246018352817' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='339.68659979265107' rx='3' width='22.445860390877083' height='20' fill='#bf103c'/>
+ <rect x='339.68659979265107' rx='3' width='22.445860390877083' height='20' fill='url(#shade)'/>
+ <rect x='340.18913403911733' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='323.24073940177396' rx='3' width='22.948394637343355' height='20' fill='#bf103c'/>
+ <rect x='323.24073940177396' rx='3' width='22.948394637343355' height='20' fill='url(#shade)'/>
+ <rect x='323.7586295288612' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='306.2923447644306' rx='3' width='23.466284764430597' height='20' fill='#bf103c'/>
+ <rect x='306.2923447644306' rx='3' width='23.466284764430597' height='20' fill='url(#shade)'/>
+ <rect x='306.82606' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='288.82606' rx='3' width='24.0' height='20' fill='#00f244'/>
+ <rect x='288.82606' rx='3' width='24.0' height='20' fill='url(#shade)'/>
+ <rect x='288.82606' rx='3' width='8' height='20' fill='url(#shadow)'/>
+ <rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='#00f244'/>
+ <rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='url(#shade)'/>
+ <rect width='169.18729000000002' height='20' fill='#404040'/>
+ <rect x='-6.0' rx='3' width='175.18729000000002' height='20' fill='url(#shade)'/>
+ <rect width='2' height='20' fill='url(#left-light)'/>
+ <rect x='657.058159125822' width='2' height='20' fill='url(#right-shadow)'/>
+ <rect width='659.058159125822' height='20' fill='url(#light)'/>
+ </g>
+ <g fill='#fff' text-anchor='middle' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='11'>
+ <svg x='6.5' y='3.0' width='16.0' height='16.0' viewBox='0 0 150 150'>
+ <polygon fill='#402a14' fill-opacity='0.5' points='84.84 10 34.1 44.46 34.1 103.78 84.84 68.02 135.57 103.78 135.57 44.46 84.84 10'/>
+ <polygon fill='#402a14' fill-opacity='0.5' points='84.84 68.02 84.84 10 135.57 44.46 135.57 103.78 84.84 68.02'/>
+ <polygon fill='#061a29' fill-opacity='0.5' points='65.07 81.99 14.34 46.22 14.34 105.54 65.07 140 115.81 105.54 115.81 46.22 65.07 81.99'/>
+ <polygon fill='#061a29' fill-opacity='0.5' points='65.07 81.99 65.07 140 14.34 105.54 14.34 46.22 65.07 81.99'/>
+ </svg>
+ <svg x='6.0' y='2.0' width='16.0' height='16.0' viewBox='0 0 150 150'>
+ <linearGradient id='yellow-shaded' x1='91.17' y1='44.83' x2='136.24' y2='73.4' gradientUnits='userSpaceOnUse'>
+ <stop offset='0.01' stop-color='#c6783e'/>
+ <stop offset='0.54' stop-color='#ff9750'/>
+ </linearGradient>
+ <linearGradient id='blue-shaded' x1='60.71' y1='104.56' x2='-15.54' y2='63' gradientUnits='userSpaceOnUse'>
+ <stop offset='0' stop-color='#005a8e'/>
+ <stop offset='0.54' stop-color='#1a7db6'/>
+ </linearGradient>
+ <polygon fill='#ff9d4b' points='84.84 10 34.1 44.46 34.1 103.78 84.84 68.02 135.57 103.78 135.57 44.46 84.84 10'/>
+ <polygon fill='url(#yellow-shaded)' points='84.84 68.02 84.84 10 135.57 44.46 135.57 103.78 84.84 68.02'/>
+ <polygon fill='#1a7db6' points='65.07 81.99 14.34 46.22 14.34 105.54 65.07 140 115.81 105.54 115.81 46.22 65.07 81.99'/>
+ <polygon fill='url(#blue-shaded)' points='65.07 81.99 65.07 140 14.34 105.54 14.34 46.22 65.07 81.99'/>
+ </svg>
+ <text font-size='11' x='96.09364500000001' y='15' fill='#000' fill-opacity='.4' textLength='135.18729000000002'>tenant.application.default</text>
+ <text font-size='11' x='95.59364500000001' y='14' fill='#fff' textLength='135.18729000000002'>tenant.application.default</text>
+ <text font-size='11' x='232.506675' y='15' fill='#000' fill-opacity='.4' textLength='113.63876999999998'>production-us-west-1</text>
+ <text font-size='11' x='232.006675' y='14' fill='#fff' textLength='113.63876999999998'>production-us-west-1</text>
+ </g>
+</svg>
diff --git a/document/src/main/java/com/yahoo/document/DataType.java b/document/src/main/java/com/yahoo/document/DataType.java
index 104d63cae96..fd7ccfc5e96 100644
--- a/document/src/main/java/com/yahoo/document/DataType.java
+++ b/document/src/main/java/com/yahoo/document/DataType.java
@@ -54,7 +54,7 @@ public abstract class DataType extends Identifiable implements Serializable, Com
public final static NumericDataType BYTE = new NumericDataType("byte", 16, ByteFieldValue.class, ByteFieldValue.getFactory());
public final static PrimitiveDataType PREDICATE = new PrimitiveDataType("predicate", 20, PredicateFieldValue.class, PredicateFieldValue.getFactory());
public final static int tensorDataTypeCode = 21; // All TensorDataType instances have id=21 but carries additional type information serialized separately
- // ADDITIONAL parametrized types added at runtime: map, struct, array, weighted set, annotation reference, tensor
+ // ADDITIONAL parametrized types added at runtime: map, struct, array, weighted set, annotation reference, tensor
// Tags are converted to weightedset<string> when reading the search definition TODO: Remove it
public final static WeightedSetDataType TAG = new WeightedSetDataType(DataType.STRING, true, true);