Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Tarantool CE versions matrix and Docker layers caching in CI #108

Merged
merged 3 commits into from
Jul 25, 2021
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
21 changes: 18 additions & 3 deletions .github/workflows/ubuntu-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,41 @@ on:
branches: [ master ]

jobs:
build:

tests-ce:
runs-on: ubuntu-latest

strategy:
matrix:
tarantool-version: [ "1.10", "2.8" ]
fail-fast: false
steps:
- uses: actions/checkout@v2

- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8

- name: Cache Maven packages
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2

- name: Cache docker images
uses: satackey/[email protected]
continue-on-error: true
with:
key: ${{ runner.os }}-docker-layer-cache-${{ matrix.tarantool-version }}
restore-keys: |
${{ runner.os }}-docker-layer-cache-

- name: Build with Maven
run: mvn -B verify --file pom.xml

- name: Run integration tests
env:
TARANTOOL_VERSION: ${{ matrix.tarantool-version }}
TARANTOOL_SERVER_USER: root
TARANTOOL_SERVER_GROUP: root
run: mvn -B test -P integration --file pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,23 @@ public class TarantoolErrors {
private enum ErrorsCodes {
NO_CONNECTION("77"), TIMEOUT("78");
private final String code;

ErrorsCodes(String code) {
this.code = code;
}

public String getCode() {
return code;
}
}

private static final String CLIENT_ERROR = "ClientError";

/**
* Produces {@link TarantoolInternalException} subclasses
* from the serialized representation in the format of <code>require('errors').new_class("NewError")</code>,
* @see <a href="https://github.com/tarantool/errors">tarantool/errors</a>
*
* @see <a href="https://github.com/tarantool/errors">tarantool/errors</a>
*/
public static class TarantoolErrorsErrorFactory implements TarantoolErrorFactory {
private static final StringValue LINE = ValueFactory.newString("line");
Expand All @@ -49,12 +52,10 @@ public static class TarantoolErrorsErrorFactory implements TarantoolErrorFactory
private static final StringValue ERROR_MESSAGE = ValueFactory.newString("str");
private static final StringValue STACKTRACE = ValueFactory.newString("stack");
private static final Pattern NETWORK_ERROR_PATTERN = Pattern.compile(
".*" +
"\"code\":" +
"[" + ErrorsCodes.NO_CONNECTION.getCode() + "|" + ErrorsCodes.TIMEOUT.getCode() + "]" +
".*" +
"\"type\":\"" + CLIENT_ERROR + "\"" +
".*", Pattern.DOTALL);
"(?=.*\"type\":\"" + CLIENT_ERROR + "\")"
+ "(?=.*\"code\":"
+ "[" + ErrorsCodes.NO_CONNECTION.getCode() + "|" + ErrorsCodes.TIMEOUT.getCode() + "])",
Pattern.DOTALL);

public TarantoolErrorsErrorFactory() {
}
Expand All @@ -67,7 +68,7 @@ public Optional<TarantoolException> create(Value error) {
Map<Value, Value> map = error.asMapValue().map();

String exceptionMessage = "";
String errorMessage = map.containsKey(ERROR_MESSAGE) ? map.get(ERROR_MESSAGE).toString() : null;
String errorMessage = map.containsKey(ERROR_MESSAGE) ? map.get(ERROR_MESSAGE).toString() : null;
String err = map.containsKey(ERR) ? map.get(ERR).toString() : null;
String line = map.containsKey(LINE) ? map.get(LINE).toString() : null;
String className = map.containsKey(CLASS_NAME) ? map.get(CLASS_NAME).toString() : null;
Expand Down Expand Up @@ -133,8 +134,8 @@ private Boolean isErrorsError(String errorMessage) {
/**
* Produces {@link TarantoolInternalException} subclasses from the serialized representation
* in the format of <code>box.error:unpack</code>,
* @see <a href="https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_error/error/">box_error</a>
*
* @see <a href="https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_error/error/">box_error</a>
*/
public static class TarantoolBoxErrorFactory implements TarantoolErrorFactory {
private static final StringValue CODE = ValueFactory.newString("code");
Expand Down Expand Up @@ -236,7 +237,7 @@ private Boolean isNetworkError(String code) {
/**
* Check the error message contains fields of code and message
*
* @param code code from box.error
* @param code code from box.error
* @param message string message from box.error
* @return an {@link Boolean}
*/
Expand All @@ -249,7 +250,6 @@ private Boolean isBoxError(String code, String message) {
* The factory is finalizing, i.e. errors passed into
* it will always be introverted as appropriate for the given factory
* The error is generated in a message that is passed to {@link TarantoolInternalException}
*
*/
public static class TarantoolUnrecognizedErrorFactory implements TarantoolErrorFactory {
public TarantoolUnrecognizedErrorFactory() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ private ProxyTarantoolTupleClient setupClient() {
private RetryingTarantoolTupleClient setupRetryingClient(int retries) {
ProxyTarantoolTupleClient client = setupClient();
return new RetryingTarantoolTupleClient(client,
TarantoolRequestRetryPolicies
.byNumberOfAttempts(retries).build());
TarantoolRequestRetryPolicies
.byNumberOfAttempts(retries).build());
}

@Test
Expand All @@ -58,14 +58,13 @@ void testNetworkError_boxErrorUnpackNoConnection() {
client.callForSingleResult("box_error_unpack_no_connection", HashMap.class).get();
fail("Exception must be thrown after last retry attempt.");
} catch (Throwable e) {
String message = e.getCause().getMessage();

assertTrue(e.getCause() instanceof TarantoolInternalNetworkException);
assertTrue(e.getCause().getMessage().contains(
"code: 77\n" +
"message: Connection is not established\n" +
"base_type: ClientError\n" +
"type: ClientError\n" +
"trace:")
);
assertTrue(message.contains("code: 77"));
assertTrue(message.contains("message: Connection is not established"));
assertTrue(message.contains("type: ClientError"));
assertTrue(message.contains("trace:"));
}
}

Expand All @@ -80,14 +79,13 @@ void testNetworkError_boxErrorUnpackTimeout() {
String.class).get();
fail("Exception must be thrown after last retry attempt.");
} catch (Throwable e) {
String message = e.getCause().getMessage();

assertTrue(e.getCause() instanceof TarantoolInternalNetworkException);
assertTrue(e.getCause().getMessage().contains(
"code: 78\n" +
"message: Timeout exceeded\n" +
"base_type: ClientError\n" +
"type: ClientError\n" +
"trace:")
);
assertTrue(message.contains("code: 78"));
assertTrue(message.contains("message: Timeout exceeded"));
assertTrue(message.contains("type: ClientError"));
assertTrue(message.contains("trace:"));
}
}

Expand All @@ -102,12 +100,11 @@ void testNetworkError_boxErrorTimeout() {
String.class).get();
fail("Exception must be thrown after last retry attempt.");
} catch (Throwable e) {
String message = e.getCause().getMessage();

assertTrue(e.getCause() instanceof TarantoolInternalNetworkException);
assertTrue(e.getCause().getMessage().contains(
"InnerErrorMessage:\n" +
"code: 78\n" +
"message: Timeout exceeded")
);
assertTrue(message.contains("code: 78"));
assertTrue(message.contains("message: Timeout exceeded"));
}
}

Expand All @@ -119,13 +116,13 @@ void testNetworkError_crudErrorTimeout() {
client.callForSingleResult("crud_error_timeout", HashMap.class).get();
fail("Exception must be thrown after last retry attempt.");
} catch (Throwable e) {
String message = e.getCause().getMessage();

assertTrue(e.getCause() instanceof TarantoolInternalNetworkException);
assertTrue(e.getCause().getMessage().contains(
"Function returned an error: {\"code\":78," +
"\"base_type\":\"ClientError\"," +
"\"type\":\"ClientError\"," +
"\"message\":\"Timeout exceeded\","
));
assertTrue(message.contains("\"code\":78"));
assertTrue(message.contains("\"type\":\"ClientError\""));
assertTrue(message.contains("\"message\":\"Timeout exceeded\""));
assertTrue(message.contains("\"trace\":"));
}
}

Expand All @@ -137,33 +134,32 @@ void testNonNetworkError_boxErrorUnpack() {
client.callForSingleResult("box_error_non_network_error", HashMap.class).get();
fail("Exception must be thrown after last retry attempt.");
} catch (Throwable e) {
String message = e.getCause().getMessage();

assertTrue(e.getCause() instanceof TarantoolInternalException);
assertFalse(e.getCause() instanceof TarantoolInternalNetworkException);
assertTrue(e.getCause().getMessage().contains(
"code: 40\n" +
"message: Failed to write to disk\n" +
"base_type: ClientError\n" +
"type: ClientError\n" +
"trace:")
);
assertTrue(message.contains("code: 40"));
assertTrue(message.contains("message: Failed to write to disk"));
assertTrue(message.contains("type: ClientError"));
assertTrue(message.contains("trace:"));
}
}

@Test
void testNonNetworkError_boxError() {
try {
ProxyTarantoolTupleClient client = setupClient();

client.callForSingleResult("raising_error", HashMap.class).get();
fail("Exception must be thrown after last retry attempt.");
} catch (Throwable e) {
assertTrue(e.getCause() instanceof TarantoolInternalException);
assertFalse(e.getCause() instanceof TarantoolInternalNetworkException);
assertTrue(e.getCause().getMessage().contains(
"InnerErrorMessage:\n" +
"code: 32\n" +
"message:")
);
}
@Test
void testNonNetworkError_boxError() {
try {
ProxyTarantoolTupleClient client = setupClient();

client.callForSingleResult("raising_error", HashMap.class).get();
fail("Exception must be thrown after last retry attempt.");
} catch (Throwable e) {
String message = e.getCause().getMessage();

assertTrue(e.getCause() instanceof TarantoolInternalException);
assertFalse(e.getCause() instanceof TarantoolInternalNetworkException);
assertTrue(message.contains("InnerErrorMessage:"));
assertTrue(message.contains("code: 32"));
assertTrue(message.contains("message:"));
}
}
}
24 changes: 15 additions & 9 deletions src/test/resources/cartridge/app/roles/api_router.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
local vshard = require('vshard')
local cartridge_pool = require('cartridge.pool')
local cartridge_rpc = require('cartridge.rpc')
local fiber = require('fiber')
local crud = require('crud')
local log = require('log')

local function get_schema()
Expand Down Expand Up @@ -31,7 +31,7 @@ local function retrying_function()
end

local function get_composite_data(id)
local data = vshard.router.callro(vshard.router.bucket_id(id), 'get_composite_data', {id})
local data = vshard.router.callro(vshard.router.bucket_id(id), 'get_composite_data', { id })
return data
end

Expand All @@ -57,7 +57,7 @@ local function raising_error(message)
end

local function reset_request_counters()
box.space.request_counters:replace({1, 0})
box.space.request_counters:replace({ 1, 0 })
end

local function get_router_name()
Expand All @@ -77,15 +77,18 @@ local function long_running_function(values)
end
end

box.space.request_counters:update(1, {{'+', 'count', 1}})
-- need using number instead field name as string in update function for compatibility with tarantool 1.10
box.space.request_counters:update(1, { { '+', 2, 1 } })
log.info('Executing long-running function ' ..
tostring(box.space.request_counters:get(1)[2]) ..
"(name: " .. disabled_router_name ..
"; sleep: " .. seconds_to_sleep .. ")")
if get_router_name() == disabled_router_name then
return nil, "Disabled by client; router_name = " .. disabled_router_name
return nil, "Disabled by client; router_name = " .. disabled_router_name
end
if seconds_to_sleep then
fiber.sleep(seconds_to_sleep)
end
if seconds_to_sleep then fiber.sleep(seconds_to_sleep) end
return true
end

Expand All @@ -111,16 +114,19 @@ local function box_error_non_network_error()
end

local function crud_error_timeout()
return crud.get("test_space", ('x'):rep(2^27))
return nil, { class_name = 'SelectError',
err = 'Failed to get next object: GetTupleError: Failed to get tuples from storages: UpdateTuplesError: Failed to select tuples from storages: Call: Failed for 07d14fec-f32b-4b90-aa72-e6755273ad56: Function returned an error: {\"code\":78,\"base_type\":\"ClientError\",\"type\":\"ClientError\",\"message\":\"Timeout exceeded\",\"trace\":[{\"file\":\"builtin\\/box\\/net_box.lua\",\"line\":419}]}',
str = 'SelectError: Failed to get next object: GetTupleError: Failed to get tuples from storages: UpdateTuplesError: Failed to select tuples from storages: Call: Failed for 07d14fec-f32b-4b90-aa72-e6755273ad56: Function returned an error: {\"code\":78,\"base_type\":\"ClientError\",\"type\":\"ClientError\",\"message\":\"Timeout exceeded\",\"trace\":[{\"file\":\"builtin\\/box\\/net_box.lua\",\"line\":419}]}'
}
end

local function init(opts)

box.schema.space.create('request_counters', {
format = {{'id', 'unsigned'}, {'count', 'unsigned'}},
format = { { 'id', 'unsigned' }, { 'count', 'unsigned' } },
if_not_exists = true
})
box.space.request_counters:create_index('primary', {parts = {'id'}, if_not_exists = true})
box.space.request_counters:create_index('id', { parts = { 'id' }, if_not_exists = true })

rawset(_G, 'truncate_space', truncate_space)

Expand Down