diff options
Diffstat (limited to 'vespaclient-container-plugin/src/main')
3 files changed, 88 insertions, 9 deletions
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java index e7ed9ce10db..6a811eb5afd 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandler.java @@ -27,11 +27,66 @@ public interface OperationHandler { public final Optional<String> cluster; public final Optional<String> continuation; public final Optional<Integer> wantedDocumentCount; + public final Optional<String> fieldSet; + public final Optional<Integer> concurrency; + /** @deprecated Use a VisitOptions.Builder instead */ + @Deprecated public VisitOptions(Optional<String> cluster, Optional<String> continuation, Optional<Integer> wantedDocumentCount) { this.cluster = cluster; this.continuation = continuation; this.wantedDocumentCount = wantedDocumentCount; + this.fieldSet = Optional.empty(); + this.concurrency = Optional.empty(); + } + + private VisitOptions(Builder builder) { + this.cluster = Optional.ofNullable(builder.cluster); + this.continuation = Optional.ofNullable(builder.continuation); + this.wantedDocumentCount = Optional.ofNullable(builder.wantedDocumentCount); + this.fieldSet = Optional.ofNullable(builder.fieldSet); + this.concurrency = Optional.ofNullable(builder.concurrency); + } + + public static class Builder { + String cluster; + String continuation; + Integer wantedDocumentCount; + String fieldSet; + Integer concurrency; + + public Builder cluster(String cluster) { + this.cluster = cluster; + return this; + } + + public Builder continuation(String continuation) { + this.continuation = continuation; + return this; + } + + public Builder wantedDocumentCount(Integer count) { + this.wantedDocumentCount = count; + return this; + } + + public Builder fieldSet(String fieldSet) { + this.fieldSet = fieldSet; + return this; + } + + public Builder concurrency(Integer concurrency) { + this.concurrency = concurrency; + return this; + } + + public VisitOptions build() { + return new VisitOptions(this); + } + } + + public static Builder builder() { + return new Builder(); } } diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandlerImpl.java b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandlerImpl.java index 46678ea67e3..1b13910cd5d 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandlerImpl.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/OperationHandlerImpl.java @@ -338,14 +338,14 @@ public class OperationHandlerImpl implements OperationHandler { VisitorParameters params = new VisitorParameters(selection.toString()); // Only return fieldset that is part of the document. - params.fieldSet(restUri.getDocumentType() + ":[document]"); + params.fieldSet(options.fieldSet.orElse(restUri.getDocumentType() + ":[document]")); params.setMaxBucketsPerVisitor(1); params.setMaxPending(32); params.setMaxFirstPassHits(1); params.setMaxTotalHits(options.wantedDocumentCount .map(n -> Math.min(Math.max(n, 1), WANTED_DOCUMENT_COUNT_UPPER_BOUND)) .orElse(1)); - params.setThrottlePolicy(new StaticThrottlePolicy().setMaxPendingCount(1)); + params.setThrottlePolicy(new StaticThrottlePolicy().setMaxPendingCount(options.concurrency.orElse(1))); params.setToTimestamp(0L); params.setFromTimestamp(0L); params.setSessionTimeoutMs(VISIT_TIMEOUT_MS); diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/RestApi.java b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/RestApi.java index d5d6a0dc40b..e710ea0a9f9 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/RestApi.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/RestApi.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.yahoo.jdisc.Metric; import com.yahoo.container.handler.ThreadpoolConfig; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; @@ -54,6 +53,8 @@ public class RestApi extends LoggingRequestHandler { private static final String CLUSTER = "cluster"; private static final String CONTINUATION = "continuation"; private static final String WANTED_DOCUMENT_COUNT = "wantedDocumentCount"; + private static final String FIELD_SET = "fieldSet"; + private static final String CONCURRENCY = "concurrency"; private static final String APPLICATION_JSON = "application/json"; private final OperationHandler operationHandler; private SingleDocumentParser singleDocumentParser; @@ -122,9 +123,17 @@ public class RestApi extends LoggingRequestHandler { return property.map(RestApi::parseBooleanStrict); } - private static Optional<Integer> parseInteger(String parameter, HttpRequest request) throws NumberFormatException { + private static int parsePositiveInt(String str) throws NumberFormatException { + int parsed = Integer.parseInt(str); + if (parsed <= 0) { + throw new IllegalArgumentException("Parsed number was negative or zero"); + } + return parsed; + } + + private static Optional<Integer> parsePositiveIntegerRequestParameter(String parameter, HttpRequest request) throws NumberFormatException { Optional<String> property = requestProperty(parameter, request); - return property.map(Integer::parseInt); + return property.map(RestApi::parsePositiveInt); } @Override @@ -255,17 +264,32 @@ public class RestApi extends LoggingRequestHandler { documentSelection = "id.group='" + group.value + "'"; } } + // TODO can refactor this quite a bit with Builder in place... Optional<String> cluster = Optional.ofNullable(request.getProperty(CLUSTER)); Optional<String> continuation = Optional.ofNullable(request.getProperty(CONTINUATION)); + Optional<String> fieldSet = Optional.ofNullable(request.getProperty(FIELD_SET)); Optional<Integer> wantedDocumentCount; try { - wantedDocumentCount = parseInteger(WANTED_DOCUMENT_COUNT, request); + wantedDocumentCount = parsePositiveIntegerRequestParameter(WANTED_DOCUMENT_COUNT, request); } catch (IllegalArgumentException e) { - return createInvalidParameterResponse(WANTED_DOCUMENT_COUNT, "Expected integer"); + return createInvalidParameterResponse(WANTED_DOCUMENT_COUNT, "Expected positive integer"); } + // TODO refactor + Optional<Integer> concurrency; + try { + concurrency = parsePositiveIntegerRequestParameter(CONCURRENCY, request); + } catch (IllegalArgumentException e) { + return createInvalidParameterResponse(CONCURRENCY, "Expected positive integer"); + } + + final OperationHandler.VisitOptions.Builder optionsBuilder = OperationHandler.VisitOptions.builder(); + cluster.ifPresent(c -> optionsBuilder.cluster(c)); + continuation.ifPresent(c -> optionsBuilder.continuation(c)); + wantedDocumentCount.ifPresent(count -> optionsBuilder.wantedDocumentCount(count)); + fieldSet.ifPresent(fs -> optionsBuilder.fieldSet(fs)); + concurrency.ifPresent(c -> optionsBuilder.concurrency(c)); - final OperationHandler.VisitOptions options = new OperationHandler.VisitOptions(cluster, continuation, wantedDocumentCount); - final OperationHandler.VisitResult visit = operationHandler.visit(restUri, documentSelection, options); + final OperationHandler.VisitResult visit = operationHandler.visit(restUri, documentSelection, optionsBuilder.build()); final ObjectNode resultNode = mapper.createObjectNode(); visit.token.ifPresent(t -> resultNode.put(CONTINUATION, t)); resultNode.putArray(DOCUMENTS).addPOJO(visit.documentsAsJsonList); |