Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
strategy:
fail-fast: false
matrix:
tarantool-version: [ "2.11.8-ubuntu20.04", "3.4.2", "3.8.1" ]
tarantool-version: [ "2.11.8-ubuntu20.04", "3.4.2", "3.8.2" ]
timeout-minutes: 40
steps:
- uses: actions/checkout@v6
Expand Down Expand Up @@ -124,7 +124,7 @@ jobs:
strategy:
fail-fast: false
matrix:
tarantool-version: [ "2.11.8-ubuntu20.04", "3.4.2", "3.8.1" ]
tarantool-version: [ "2.11.8-ubuntu20.04", "3.4.2", "3.8.2" ]
timeout-minutes: 40
steps:
- uses: actions/checkout@v6
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
[LINEARIZABLE](https://github.com/tarantool/tarantool/blob/e643f88a5e0c6d9ef2789b2033088fd04e7d39ae/src/box/txn.h#L228)
isolation level.

### Protocol

- Added processing
for [MP_ERROR](https://www.tarantool.io/en/doc/latest/reference/internals/msgpack_extensions/#the-error-type),
which is returned as an object within a response of type OK.

### Testcontainers

- `CartridgeClusterContainer`: a failed `cartridge replicasets setup` from a YAML topology file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,73 +6,101 @@
package io.tarantool.core.exceptions;

import java.util.List;
import java.util.stream.Collectors;

import org.msgpack.value.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static io.tarantool.core.protocol.requests.IProtoConstant.IPROTO_ERROR;
import static io.tarantool.core.protocol.requests.IProtoConstant.IPROTO_ERROR_24;
import static io.tarantool.core.protocol.requests.IProtoConstant.MP_ERROR_STACK;
import io.tarantool.core.protocol.IProtoMessage;
import io.tarantool.core.protocol.requests.IProtoConstant;

public class BoxError extends RuntimeException {

private static final long serialVersionUID = -407469439059293836L;
private static final Logger LOGGER = LoggerFactory.getLogger(BoxError.class);

private final int code;
private final String tarantoolMessage;
private final List<BoxErrorStackItem> stack;

private StringBuilder sb;
private final BoxErrorValue error;
private final String err24;

public static BoxError fromIProtoMessage(IProtoMessage packet) {
return new BoxError(
packet.getErrorCode(),
packet.getBodyStringValue(IPROTO_ERROR_24).asString(),
packet
.getBodyMapValue(IPROTO_ERROR)
.map()
.get(MP_ERROR_STACK)
.asArrayValue()
.list()
.stream()
.map(Value::asMapValue)
.map(BoxErrorStackItem::fromStruct)
.collect(Collectors.toList()));
final Value rawError = packet.getBodyValue(IProtoConstant.IPROTO_ERROR);
if (rawError == null || rawError.isNilValue()) {
LOGGER.error("IPROTO_ERROR must not be null!");
throw new NullPointerException("IPROTO_ERROR must not be null!");
}
final BoxErrorValue err = BoxErrorValue.from(rawError);

final String err24 = extractErr24(packet.getBodyValue(IProtoConstant.IPROTO_ERROR_24));
return new BoxError(packet.getErrorCode(), err24, err);
}

private BoxError(int code, String tarantoolMessage, List<BoxErrorStackItem> stack) {
private BoxError(int code, String err24, BoxErrorValue error) {
this.code = code;
this.tarantoolMessage = tarantoolMessage;
this.stack = stack;
this.err24 = err24;
this.error = error;
}

@Override
public String getMessage() {
if (sb == null) {
sb =
new StringBuilder("BoxError{")
.append("code=")
.append(code)
.append(", message='")
.append(tarantoolMessage)
.append('\'')
.append(", stack=")
.append(stack)
.append('}');
}
return this.sb.toString();
return "BoxError{code='"
+ this.code
+ "', message='"
+ this.err24
+ "', stack="
+ this.error.stack()
+ '}';
}

/**
* @deprecated use {@link #tarantoolMessage()} instead this.
*/
@Deprecated
public String getTarantoolMessage() {
return tarantoolMessage;
return tarantoolMessage();
}

/** Returns {@link IProtoConstant#IPROTO_ERROR_24} value. */
public String tarantoolMessage() {
return this.err24;
}

/**
* @deprecated use {@link #stack()} instead this.
*/
@Deprecated
public List<BoxErrorStackItem> getTarantoolStack() {
return this.stack;
return this.error.stack();
}

/** Returns {@link IProtoConstant#MP_ERROR_STACK} errors stack. */
public List<BoxErrorStackItem> stack() {
return this.error.stack();
}

/**
* @deprecated use {@link #errorCode()} instead this.
*/
@Deprecated
public int getErrorCode() {
return errorCode();
}

/** Returns error code from response. */
public int errorCode() {
return this.code;
}

private static String extractErr24(Value rawErr24) {
if (rawErr24 == null || rawErr24.isNilValue()) {
LOGGER.error("ERROR_24 must not be null! Current: '{}'", rawErr24);
throw new NullPointerException("ERROR_24 must not be null!");
Comment thread
bitgorbovsky marked this conversation as resolved.
Resolved
}

if (!rawErr24.isStringValue()) {
LOGGER.error("IPROTO_ERROR_24 must be String. Current: '{}'", rawErr24);
throw new IllegalArgumentException("IPROTO_ERROR_24 must be String!");
}
return rawErr24.asStringValue().asString();
}
}
Loading
Loading