All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.couchbase.client.core.io.netty.kv.ErrorMap Maven / Gradle / Ivy

There is a newer version: 2.7.0
Show newest version
/*
 * Copyright (c) 2018 Couchbase, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.couchbase.client.core.io.netty.kv;

import com.couchbase.client.core.deps.com.fasterxml.jackson.annotation.JsonCreator;
import com.couchbase.client.core.deps.com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.couchbase.client.core.deps.com.fasterxml.jackson.annotation.JsonProperty;
import com.couchbase.client.core.deps.com.fasterxml.jackson.annotation.JsonValue;
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.DeserializationFeature;
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.ObjectReader;
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.couchbase.client.core.json.Mapper;

import java.io.IOException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * The {@link ErrorMap} contains mappings from errors to their attributes, negotiated
 * between the client and the server.
 *
 * 

From the documentation:

* *

An Error Map is a mapping of error to their attributes and properties. It is used by * connected clients to handle error codes which they may otherwise not be aware of.

* *

The error map solves the problem where clients would incorrectly handle newer error codes, * and/or where the server would disconnect the client because it needed to send it a new * error code.

* *

The solution via Error Map is to establish a contract between client and server about certain * attributes which each error code may have. These attributes indicate whether an error may be * passed through, whether the command is retriable and so on. When a client receives an error code * it does not know about it, it can look up its attributes and then determine the next course of * action.

* * @since 1.4.4 */ @JsonIgnoreProperties(ignoreUnknown = true) public class ErrorMap implements Comparable { private static final ObjectReader objectReader = Mapper.reader().forType(ErrorMap.class) .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); private final int version; private final int revision; private final Map errors; /** * Creates a new ErrorMap by parsing the json representation. * * @throws IOException if parsing failed */ public static ErrorMap fromJson(byte[] jsonBytes) throws IOException { return objectReader.readValue(jsonBytes); } /** * Creates a new Error Map, usually called from jackson. * * @param version the error map version. * @param revision the error map revision. * @param errors the full error section. */ @JsonCreator public ErrorMap( @JsonProperty("version") int version, @JsonProperty("revision") int revision, @JsonProperty("errors") Map errors) { this.version = version; this.revision = revision; this.errors = toShortKeys(errors); } private static Map toShortKeys(Map errors) { Map result = new HashMap(errors.size()); for (Map.Entry entry : errors.entrySet()) { result.put(Short.parseShort(entry.getKey(), 16), entry.getValue()); } return result; } @Override public int compareTo(ErrorMap o) { if (version < o.version()) { return -1; } else if (version > o.version()) { return 1; } if (revision < o.revision()) { return -1; } else if (revision > o.revision()) { return 1; } return 0; } public int version() { return version; } public int revision() { return revision; } public Map errors() { return errors; } @JsonIgnoreProperties(ignoreUnknown = true) public static class ErrorCode { private final String name; private final String description; private final Set attributes; private final RetrySpecification retrySpec; /** * Creates a new error code, usually called from jackson. * * @param name name of the error code. * @param description description of the error code. * @param attributes the attributes for each error. * @param retrySpec the retry specification for the error code. */ @JsonCreator public ErrorCode( @JsonProperty("name") String name, @JsonProperty("desc") String description, @JsonProperty("attrs") @JsonDeserialize(as = EnumSet.class) Set attributes, @JsonProperty("retry") RetrySpecification retrySpec) { this.name = name; this.description = description; this.attributes = attributes; this.retrySpec = retrySpec; } public String name() { return name; } public String description() { return description; } public Set attributes() { return attributes; } public RetrySpecification retrySpec() { return retrySpec; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ErrorCode{"); sb.append("name='" + name + '\''); sb.append(", description='" + description + '\''); sb.append(", attributes=" + attributes); if (retrySpec != null) { sb.append(", retryHint=" + retrySpec.toString()); } sb.append("}"); return sb.toString(); } } public enum ErrorAttribute { /** * The operation was successful for those situations * where the error code is indicating successful (i.e. subdoc * operations carried out on a deleted document) */ SUCCESS("success"), /** * This attribute means that the error is related to a constraint * failure regarding the item itself, i.e. the item does not exist, * already exists, or its current value makes the current operation * impossible. Retrying the operation when the item's value or status * has changed may succeed. */ ITEM_ONLY("item-only"), /** * This attribute means that a user's input was invalid because it * violates the semantics of the operation, or exceeds some predefined * limit. */ INVALID_INPUT("invalid-input"), /** * The client's cluster map may be outdated and requires updating. The * client should obtain a newer configuration. */ FETCH_CONFIG("fetch-config"), /** * The current connection is no longer valid. The client must reconnect * to the server. Note that the presence of other attributes may indicate * an alternate remedy to fixing the connection without a disconnect, but * without special remedial action a disconnect is needed. */ CONN_STATE_INVALIDATED("conn-state-invalidated"), /** * The operation failed because the client failed to authenticate or is not authorized * to perform this operation. Note that this error in itself does not mean the connection * is invalid, unless conn-state-invalidated is also present. */ AUTH("auth"), /** * This error code must be handled specially. If it is not handled, the connection must be * dropped. */ SPECIAL_HANDLING("special-handling"), /** * The operation is not supported, possibly because the of server version, bucket type, or * current user. */ SUPPORT("support"), /** * This error is transient. Note that this does not mean the error is retriable. */ TEMP("temp"), /** * This is an internal error in the server. */ INTERNAL("internal"), /** * The operation may be retried immediately. */ RETRY_NOW("retry-now"), /** * The operation may be retried after some time. */ RETRY_LATER("retry-later"), /** * The error is related to the subdocument subsystem. */ SUBDOC("subdoc"), /** * The error is related to the DCP subsystem. */ DCP("dcp"), /** * Use retry specifications from the server. */ AUTO_RETRY("auto-retry"), /** * This attribute specifies that the requested item is currently locked. */ ITEM_LOCKED("item-locked"), /** * This attribute means that the error is related * to operating on a soft-deleted document. */ ITEM_DELETED("item-deleted"); private final String raw; ErrorAttribute(String raw) { this.raw = raw; } @JsonValue public String raw() { return raw; } } @JsonIgnoreProperties(ignoreUnknown = true) public static class RetrySpecification { private final RetryStrategy strategy; private final long interval; private final long after; private final long maxDuration; private final long ceil; /** * Creates a new retry specification, usually called from jackson. * * @param strategy the converted strategy. * @param interval the retry interval. * @param after after which time the retry should happen. * @param maxDuration the maximum duration of the retry. * @param ceil the ceiling of the retry delay. */ @JsonCreator public RetrySpecification( @JsonProperty("strategy") RetryStrategy strategy, @JsonProperty("interval") int interval, @JsonProperty("after") int after, @JsonProperty("max-duration") int maxDuration, @JsonProperty("ceil") int ceil) { this.strategy = strategy; this.interval = interval; this.after = after; this.maxDuration = maxDuration; this.ceil = ceil; } public RetryStrategy strategy() { return this.strategy; } public long interval() { return this.interval; } public long after() { return this.after; } public long maxDuration() { return this.maxDuration; } public long ceil() { return this.ceil; } @Override public String toString() { return "Retry{" + "strategy=" + strategy() + ", interval=" + interval() + ", after=" + after() + ", max-duration=" + maxDuration() + ", ceil=" + ceil() + "}"; } } public enum RetryStrategy { EXPONENTIAL("exponential"), LINEAR("linear"), CONSTANT("constant"); private final String strategy; RetryStrategy(String strategy) { this.strategy = strategy; } @JsonValue public String strategy() { return strategy; } } @Override public String toString() { return "ErrorMap{" + "version=" + version + ", revision=" + revision + ", errors=" + errors + '}'; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy