diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-11-28 22:06:31 +0100 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2022-11-28 22:06:31 +0100 |
commit | 0316e548e511adb448f25eb2d869d392d789e28c (patch) | |
tree | b47a70da4ba1fcfed9a3faa713a187eef5162c1a /vespaclient-core | |
parent | da38b71fa425409c5c41615bbf6ea8bcca8b9af0 (diff) |
No need to bring in container dependencies in the feeder client.
Diffstat (limited to 'vespaclient-core')
7 files changed, 127 insertions, 51 deletions
diff --git a/vespaclient-core/pom.xml b/vespaclient-core/pom.xml index 5afc2b57868..87f27248b80 100644 --- a/vespaclient-core/pom.xml +++ b/vespaclient-core/pom.xml @@ -19,7 +19,7 @@ </dependency> <dependency> <groupId>com.yahoo.vespa</groupId> - <artifactId>container-dev</artifactId> + <artifactId>documentapi</artifactId> <version>${project.version}</version> <scope>provided</scope> </dependency> diff --git a/vespaclient-core/src/main/java/com/yahoo/feedapi/MessagePropertyProcessor.java b/vespaclient-core/src/main/java/com/yahoo/feedapi/MessagePropertyProcessor.java index ac1ed248ee9..f862451c095 100644 --- a/vespaclient-core/src/main/java/com/yahoo/feedapi/MessagePropertyProcessor.java +++ b/vespaclient-core/src/main/java/com/yahoo/feedapi/MessagePropertyProcessor.java @@ -3,9 +3,9 @@ package com.yahoo.feedapi; import com.yahoo.concurrent.SystemTimer; import com.yahoo.config.subscription.ConfigSubscriber; -import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.documentapi.messagebus.protocol.DocumentMessage; import com.yahoo.documentapi.messagebus.protocol.DocumentProtocol; +import com.yahoo.feedhandler.InputStreamRequest; import com.yahoo.messagebus.Message; import com.yahoo.messagebus.routing.Route; import com.yahoo.vespaclient.config.FeederConfig; @@ -26,7 +26,6 @@ public class MessagePropertyProcessor implements ConfigSubscriber.SingleSubscrib private Route defaultRoute = null; private long defaultTimeoutMillis = 0; private boolean retryEnabled = true; - private String defaultDocprocChain = null; private boolean defaultAbortOnDocumentError = true; private boolean defaultAbortOnSendError = true; private boolean configChanged = false; @@ -39,7 +38,7 @@ public class MessagePropertyProcessor implements ConfigSubscriber.SingleSubscrib defaultRoute = Route.parse(routeOverride); } - public PropertySetter buildPropertySetter(HttpRequest request) { + public PropertySetter buildPropertySetter(InputStreamRequest request) { String routeParam = null; double timeoutParam = -1; String priorityParam = null; @@ -129,7 +128,6 @@ public class MessagePropertyProcessor implements ConfigSubscriber.SingleSubscrib log.log(Level.FINE, "Received new config (" + "route: " + (defaultRoute != null ? defaultRoute : "<none>") + ", timeout: " + defaultTimeoutMillis + " ms, retry enabled: " + retryEnabled + - ", docproc chain: " + (defaultDocprocChain != null ? defaultDocprocChain : "<none>") + ", abort on doc error: " + defaultAbortOnDocumentError + ", abort on feed error: " + defaultAbortOnSendError + ")"); } @@ -139,16 +137,16 @@ public class MessagePropertyProcessor implements ConfigSubscriber.SingleSubscrib /** Route either set by configuration or by explicit request override. May be null */ private Route route; /** Timeout (in milliseconds) */ - private long timeout; - private long totalTimeout; - private long startTime; + private final long timeout; + private final long totalTimeout; + private final long startTime; /** Explicit priority set. May be null */ private DocumentProtocol.Priority priority; - private boolean retryEnabled; - private boolean abortOnDocumentError; - private boolean abortOnFeedError; - private boolean createIfNonExistent; - private int traceLevel; + private final boolean retryEnabled; + private final boolean abortOnDocumentError; + private final boolean abortOnFeedError; + private final boolean createIfNonExistent; + private final int traceLevel; PropertySetter(Route route, long timeout, long totalTimeout, DocumentProtocol.Priority priority, boolean retryEnabled, boolean abortOnDocumentError, boolean abortOnFeedError, diff --git a/vespaclient-core/src/main/java/com/yahoo/feedhandler/FeedResponse.java b/vespaclient-core/src/main/java/com/yahoo/feedhandler/FeedResponse.java index dd95e1dc202..48ba8f83d3c 100755 --- a/vespaclient-core/src/main/java/com/yahoo/feedhandler/FeedResponse.java +++ b/vespaclient-core/src/main/java/com/yahoo/feedhandler/FeedResponse.java @@ -11,7 +11,6 @@ import com.yahoo.messagebus.Error; import com.yahoo.messagebus.ErrorCode; import com.yahoo.messagebus.Message; import com.yahoo.messagebus.Reply; -import com.yahoo.search.result.ErrorMessage; import java.util.ArrayList; import java.util.List; @@ -21,7 +20,6 @@ import java.util.stream.Stream; public final class FeedResponse implements SharedSender.ResultCallback { private final static Logger log = Logger.getLogger(FeedResponse.class.getName()); - private final List<ErrorMessage> errorMessages = new ArrayList<>(); private final List<String> errors = new ArrayList<>(); private final StringBuilder traces = new StringBuilder(); private final RouteMetricSet metrics; @@ -75,7 +73,7 @@ public final class FeedResponse implements SharedSender.ResultCallback { String str = out.toString(); log.finest(str); - addError(convertErrorCode(err.getCode()), str); + addError(err); } if (abortOnError) { isAborted = true; @@ -92,14 +90,12 @@ public final class FeedResponse implements SharedSender.ResultCallback { } FeedResponse addXMLParseError(String error) { - errorMessages.add(ErrorMessage.createBadRequest(error)); errors.add(error); return this; } - public FeedResponse addError(com.yahoo.container.protect.Error code, String error) { - errorMessages.add(new ErrorMessage(code.code, error)); - errors.add(error); + public FeedResponse addError(Error error) { + errors.add(error.toString()); return this; } @@ -111,27 +107,6 @@ public final class FeedResponse implements SharedSender.ResultCallback { return errors.anyMatch(e -> e.getCode() != DocumentProtocol.ERROR_TEST_AND_SET_CONDITION_FAILED); } - private static com.yahoo.container.protect.Error convertErrorCode(int error) { - // We should try to enumerate these error a bit finer. - // Like busy, no space etc. - if (error == DocumentProtocol.ERROR_NO_SPACE) { - return com.yahoo.container.protect.Error.INSUFFICIENT_STORAGE; - } else if (isTransientError(error)) { - return com.yahoo.container.protect.Error.INTERNAL_SERVER_ERROR; - } if (isFatalError(error)) { - return com.yahoo.container.protect.Error.INTERNAL_SERVER_ERROR; - } - return com.yahoo.container.protect.Error.INTERNAL_SERVER_ERROR; - } - - private static boolean isFatalError(int error) { - return (error >= ErrorCode.FATAL_ERROR) && (error < ErrorCode.ERROR_LIMIT); - } - - private static boolean isTransientError(int error) { - return (error >= ErrorCode.TRANSIENT_ERROR) && (error < ErrorCode.FATAL_ERROR); - } - public boolean isSuccess() { return errors.isEmpty(); } diff --git a/vespaclient-core/src/main/java/com/yahoo/feedhandler/InputStreamRequest.java b/vespaclient-core/src/main/java/com/yahoo/feedhandler/InputStreamRequest.java new file mode 100644 index 00000000000..a62ecbd55ec --- /dev/null +++ b/vespaclient-core/src/main/java/com/yahoo/feedhandler/InputStreamRequest.java @@ -0,0 +1,34 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.feedhandler; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * This is needed because whoever wrote this library moronically decided to pass in-process communication through + * the HTTP layer. As the feeded is being phased out in favor of the standalone HTTP client we don't bother to clean + * it up properly. + * + * @author bratseth + */ +public class InputStreamRequest { + + private final InputStream input; + private final Map<String, String> properties = new HashMap<>(); + + public InputStreamRequest(InputStream input) { + this.input = input; + } + + public void setProperty(String key, String value) { + properties.put(key, value); + } + + public String getProperty(String key) { + return properties.get(key); + } + + InputStream getData() { return input; } + +} diff --git a/vespaclient-core/src/main/java/com/yahoo/feedhandler/ParameterParser.java b/vespaclient-core/src/main/java/com/yahoo/feedhandler/ParameterParser.java new file mode 100644 index 00000000000..c907c5a72d8 --- /dev/null +++ b/vespaclient-core/src/main/java/com/yahoo/feedhandler/ParameterParser.java @@ -0,0 +1,71 @@ +package com.yahoo.feedhandler; + +public class ParameterParser { + + /** + * Tries to return the given object as a Long. If it is a Number, treat it + * as a number of seconds, i.e. get a Long representation and multiply by + * 1000. If it has a String representation, try to parse this as a floating + * point number, followed by by an optional unit (seconds and an SI prefix, + * a couple of valid examples are "s" and "ms". Only a very small subset of + * SI prefixes are supported). If no unit is given, seconds are assumed. + * + * @param value some representation of a number of seconds + * @param defaultValue returned if value is null + * @return value as a number of milliseconds + * @throws NumberFormatException if value is not a Number instance and its String + * representation cannot be parsed as a number followed optionally by time unit + */ + public static Long asMilliSeconds(Object value, Long defaultValue) { + if (value == null) return defaultValue; + if (value instanceof Number) return ((Number)value).longValue() * 1000L; + return parseTime(value.toString()); + } + + private static Long parseTime(String time) throws NumberFormatException { + time = time.trim(); + try { + int unitOffset = findUnitOffset(time); + double measure = Double.valueOf(time.substring(0, unitOffset)); + double multiplier = parseUnit(time.substring(unitOffset)); + return (long) (measure * multiplier); + } catch (RuntimeException e) { + throw new IllegalArgumentException("Error parsing '" + time + "'", e); + } + } + + private static int findUnitOffset(String time) { + int unitOffset = 0; + while (unitOffset < time.length()) { + char c = time.charAt(unitOffset); + if (c == '.' || (c >= '0' && c <= '9')) { + unitOffset += 1; + } else { + break; + } + } + if (unitOffset == 0) { + throw new IllegalArgumentException("Invalid number '" + time + "'"); + } + return unitOffset; + } + + private static double parseUnit(String unit) { + unit = unit.trim(); + final double multiplier; + if ("ks".equals(unit)) { + multiplier = 1e6d; + } else if ("s".equals(unit)) { + multiplier = 1000.0d; + } else if ("ms".equals(unit)) { + multiplier = 1.0d; + } else if ("\u00B5s".equals(unit)) { + // microseconds + multiplier = 1e-3d; + } else { + multiplier = 1000.0d; + } + return multiplier; + } + +} diff --git a/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandler.java b/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandler.java index 06f66c83e1b..75a8c8bd811 100755 --- a/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandler.java +++ b/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandler.java @@ -2,8 +2,6 @@ package com.yahoo.feedhandler; import com.yahoo.clientmetrics.RouteMetricSet; -import com.yahoo.container.jdisc.HttpRequest; -import com.yahoo.container.protect.Error; import com.yahoo.feedapi.FeedContext; import com.yahoo.feedapi.Feeder; import com.yahoo.feedapi.JsonFeeder; @@ -11,6 +9,8 @@ import com.yahoo.feedapi.MessagePropertyProcessor; import com.yahoo.feedapi.SimpleFeedAccess; import com.yahoo.feedapi.SingleSender; import com.yahoo.feedapi.XMLFeeder; +import com.yahoo.messagebus.Error; +import com.yahoo.messagebus.ErrorCode; import java.util.List; @@ -33,7 +33,7 @@ public final class VespaFeedHandler extends VespaFeedHandlerBase { return new VespaFeedHandler(context); } - public FeedResponse handle(HttpRequest request, RouteMetricSet.ProgressCallback callback, int numThreads) { + public FeedResponse handle(InputStreamRequest request, RouteMetricSet.ProgressCallback callback, int numThreads) { MessagePropertyProcessor.PropertySetter properties = getPropertyProcessor().buildPropertySetter(request); String route = properties.getRoute().toString(); @@ -57,15 +57,15 @@ public final class VespaFeedHandler extends VespaFeedHandlerBase { long millis = getTimeoutMillis(request); boolean completed = sender.waitForPending(millis); if (!completed) { - response.addError(Error.TIMEOUT, "Timed out after " + millis + " ms waiting for responses"); + response.addError(new Error(ErrorCode.TIMEOUT, "Timed out after " + millis + " ms waiting for responses")); } response.done(); return response; } - private Feeder createFeeder(SimpleFeedAccess sender, HttpRequest request) { - if ( ! Boolean.valueOf(request.getProperty(JSON_INPUT))) { + private Feeder createFeeder(SimpleFeedAccess sender, InputStreamRequest request) { + if ( ! Boolean.parseBoolean(request.getProperty(JSON_INPUT))) { return new XMLFeeder(getDocumentTypeManager(), sender, getRequestInputStream(request)); } return new JsonFeeder(getDocumentTypeManager(), sender, getRequestInputStream(request)); diff --git a/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerBase.java b/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerBase.java index 0ef0bf7a3ec..e0688520a70 100755 --- a/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerBase.java +++ b/vespaclient-core/src/main/java/com/yahoo/feedhandler/VespaFeedHandlerBase.java @@ -1,12 +1,10 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.feedhandler; -import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.document.DocumentTypeManager; import com.yahoo.feedapi.FeedContext; import com.yahoo.feedapi.MessagePropertyProcessor; import com.yahoo.feedapi.SharedSender; -import com.yahoo.search.query.ParameterParser; import java.io.InputStream; @@ -39,7 +37,7 @@ public abstract class VespaFeedHandlerBase { * original data stream. * @throws IllegalArgumentException if GZIP stream creation failed */ - InputStream getRequestInputStream(HttpRequest request) { + InputStream getRequestInputStream(InputStreamRequest request) { return request.getData(); } @@ -47,7 +45,7 @@ public abstract class VespaFeedHandlerBase { return context.getDocumentTypeManager(); } - protected long getTimeoutMillis(HttpRequest request) { + protected long getTimeoutMillis(InputStreamRequest request) { return ParameterParser.asMilliSeconds(request.getProperty("timeout"), defaultTimeoutMillis); } |