This is an automated email from the ASF dual-hosted git repository. CritasWang pushed a commit to branch wx/iotdb-2.0.11-alignment in repository https://gitbox.apache.org/repos/asf/iotdb-extras.git
commit 4f03d97753d1119384c2bbc6a5f7fa49741284ad Author: CritasWang <[email protected]> AuthorDate: Thu Sep 17 17:50:47 2026 +0800 thingsboard: drop per-test databases and refresh 2.0.11 notes The container ITs provisioned a fresh database per test and never dropped it; on an 8 GB Docker host the DataNode ran out of region memory after about a dozen databases and later tests timed out on their first write. Track the databases each test creates and drop them afterwards. apache/iotdb#18300 (grouped MAX of non-positive floats) ships in 2.0.11, so the DAO comment no longer claims it is unreleased; the -MIN(-x) projection stays for older servers. Remaining 2.0.8 references in the README and migration guide now name the verified 2.0.11 behavior. --- iotdb-thingsboard-table/README.md | 2 +- iotdb-thingsboard-table/docs/migration-guide.md | 4 +-- .../thingsboard/table/IoTDBTableTimeseriesDao.java | 40 +++++++++++----------- .../table/IoTDBTableAttributesDaoIT.java | 20 ++++++++++- .../table/IoTDBTableIngestionBenchmarkIT.java | 20 ++++++++++- .../thingsboard/table/IoTDBTableLatestDaoIT.java | 20 ++++++++++- .../table/IoTDBTableTimeseriesAggregationIT.java | 20 ++++++++++- .../table/IoTDBTableTimeseriesDaoIT.java | 20 ++++++++++- .../extras/thingsboard/table/IoTDBTableTtlIT.java | 21 +++++++++++- 9 files changed, 138 insertions(+), 29 deletions(-) diff --git a/iotdb-thingsboard-table/README.md b/iotdb-thingsboard-table/README.md index 777ae16..827f560 100644 --- a/iotdb-thingsboard-table/README.md +++ b/iotdb-thingsboard-table/README.md @@ -236,7 +236,7 @@ a retention window in **milliseconds**, and the accepted forms are narrow: | `TTL='INF'` | Never expire. The **quoted** string is the only accepted spelling; this is the form `entity_attributes` and `telemetry_latest` ship with. | | `TTL=DEFAULT` | Inherit the database default, which is `INF` on a fresh node. | -Anything else is rejected by IoTDB 2.0.8: an unquoted `TTL=INF` is parsed as an +Anything else is rejected by IoTDB 2.0.11 (and 2.0.8): an unquoted `TTL=INF` is parsed as an identifier (`ttl value must be a LongLiteral, but now is Identifier`), and any other quoted value — including a quoted number (`'604800000'`) or a duration (`'7d'`) — fails with `ttl value must be 'INF' or a long literal`. diff --git a/iotdb-thingsboard-table/docs/migration-guide.md b/iotdb-thingsboard-table/docs/migration-guide.md index ee46c9d..3fbba63 100644 --- a/iotdb-thingsboard-table/docs/migration-guide.md +++ b/iotdb-thingsboard-table/docs/migration-guide.md @@ -92,7 +92,7 @@ Notes: ## Before you begin - A reachable IoTDB 2.x server in **Table Mode** (the tested server is IoTDB - 2.0.8). Have its host, port, and credentials ready. + 2.0.11). Have its host, port, and credentials ready. - A ThingsBoard 4.3.1.2 build you control (the module is consumed as a compile/runtime dependency of the ThingsBoard application; it is not a drop-in for a pre-built binary distribution). @@ -227,7 +227,7 @@ ALTER TABLE telemetry SET PROPERTIES TTL=DEFAULT; -- back to the db default ``` Quoted numbers (`'604800000'`) and duration forms (`'7d'`) are rejected by IoTDB -2.0.8. The `telemetry_latest` overlay table is created `WITH (TTL='INF')` and is +2.0.11 (and 2.0.8). The `telemetry_latest` overlay table is created `WITH (TTL='INF')` and is **exempt** from the `telemetry` TTL: setting a retention window on `telemetry` does not evict overlay rows, so bound the overlay separately if needed (see *Limitations*). diff --git a/iotdb-thingsboard-table/src/main/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDao.java b/iotdb-thingsboard-table/src/main/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDao.java index 573e852..598639c 100644 --- a/iotdb-thingsboard-table/src/main/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDao.java +++ b/iotdb-thingsboard-table/src/main/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDao.java @@ -612,18 +612,17 @@ public class IoTDBTableTimeseriesDao extends IoTDBTableBaseDao // promote to DOUBLE. Project the partial long/double sums plus the long/double non-null // counts so the row mapper can pick the type without re-reading the raw rows. case SUM -> - // IoTDB 2.0.8 computes SUM over an INT64 column with a DOUBLE accumulator and returns a - // DOUBLE. Project the long partial as SUM(CAST(long_v AS DOUBLE)) -- a plain DOUBLE -- - // and - // NEVER cast it back to INT64 in SQL: CAST(SUM(long_v) AS INT64) THROWS a "Double value - // out of range of long value" error at the IoTDB level when the long-only sum exceeds - // Long.MAX, which would fail the whole aggregate query before the Java - // bound-check/fallback - // could run. The DOUBLE accumulator only keeps the sum bit-exact while every partial sum - // stays within +/-2^53, so the row mapper reads MIN(long_v)/MAX(long_v) to bound the sum, - // returns the DOUBLE cast back to long (lossless within the bound) for the provably-exact - // long-only case, and falls back to an exact Java re-sum when the bound exceeds 2^53 (see - // aggregatedSumEntry). The double partial stays DOUBLE. + // IoTDB (verified on 2.0.8 and 2.0.11) computes SUM over an INT64 column with a DOUBLE + // accumulator and returns a DOUBLE. Project the long partial as + // SUM(CAST(long_v AS DOUBLE)) -- a plain DOUBLE -- and NEVER cast it back to INT64 in + // SQL: CAST(SUM(long_v) AS INT64) THROWS a "Double value out of range of long value" + // error at the IoTDB level when the long-only sum exceeds Long.MAX, which would fail + // the whole aggregate query before the Java bound-check/fallback could run. The DOUBLE + // accumulator only keeps the sum bit-exact while every partial sum stays within + // +/-2^53, so the row mapper reads MIN(long_v)/MAX(long_v) to bound the sum, returns + // the DOUBLE cast back to long (lossless within the bound) for the provably-exact + // long-only case, and falls back to an exact Java re-sum when the bound exceeds 2^53 + // (see aggregatedSumEntry). The double partial stays DOUBLE. "SUM(CAST(long_v AS DOUBLE)) AS " + SUM_LONG_COLUMN + ", SUM(double_v) AS " @@ -660,14 +659,15 @@ public class IoTDBTableTimeseriesDao extends IoTDBTableBaseDao // `value >= state`, so a bucket whose numeric maximum is zero or negative comes back // NULL. This DAO reads a NULL aggregate as "empty bucket" and skips it, so a MAX // downsampling query over e.g. a sub-zero sensor would silently lose whole buckets - // instead of failing. Every release up to and including 2.0.10 is affected; fixed on - // master by apache/iotdb#18300, which is not in a released version yet. The grouped MIN - // accumulator seeds with MAX_VALUE and is not affected, and IEEE-754 negation is exact, - // so -MIN(-x) is an exact substitute for MAX(x) over finite values, on affected and - // fixed servers alike. This projection is shared with the calendar path, whose - // non-grouped accumulators track an explicit initialized flag rather than a sentinel, so - // the substitution is exact there too and an empty bucket still yields NULL. MAX(long_v) - // and MAX(str_v) are already correct (true Long.MIN_VALUE seed / flag-based) and stay. + // instead of failing. Every release up to and including 2.0.10 is affected; the fix + // (apache/iotdb#18300) ships in 2.0.11. The substitution is kept because the pool can be + // pointed at any 2.x server: the grouped MIN accumulator seeds with MAX_VALUE and is not + // affected, and IEEE-754 negation is exact, so -MIN(-x) is an exact substitute for MAX(x) + // over finite values, on affected and fixed servers alike. This projection is shared with + // the calendar path, whose non-grouped accumulators track an explicit initialized flag + // rather than a sentinel, so the substitution is exact there too and an empty bucket still + // yields NULL. MAX(long_v) and MAX(str_v) are already correct (true Long.MIN_VALUE seed / + // flag-based) and stay. case MAX -> "-1 * MIN(-1 * (" + NUMERIC_VALUE diff --git a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableAttributesDaoIT.java b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableAttributesDaoIT.java index 16c1c4b..a0baddc 100644 --- a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableAttributesDaoIT.java +++ b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableAttributesDaoIT.java @@ -25,6 +25,7 @@ import org.apache.iotdb.session.pool.TableSessionPoolBuilder; import com.google.common.util.concurrent.ListenableFuture; import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; @@ -69,6 +70,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Tag("integration") @Testcontainers(disabledWithoutDocker = true) class IoTDBTableAttributesDaoIT { + private final List<String> createdDatabases = new ArrayList<>(); // Cold testcontainer first writes/reads are slower than a warm production node, so the // per-future assertion timeout is generous. private static final int FUTURE_TIMEOUT_SECONDS = 30; @@ -638,12 +640,28 @@ class IoTDBTableAttributesDaoIT { new TestEntityId(UUID.fromString(entityId), EntityType.DEVICE)); } + @AfterEach + void dropCreatedDatabases() throws Exception { + // Every test provisions its own database. Drop them once the test is done: the shared + // container has a fixed region memory budget, and leaving dozens of databases behind makes + // later tests in the class fail schema-region creation ("Total allocated memory for direct + // buffer ... is greater than limit mem cost") and time out on their first write. + try (ITableSessionPool pool = newPool(null); + ITableSession session = pool.getSession()) { + for (String database : createdDatabases) { + session.executeNonQueryStatement("DROP DATABASE IF EXISTS " + database); + } + } + } + private String uniqueDatabase(String prefix) { // IoTDB caps database names at 64 chars; keep the per-test prefix short and append a trimmed // UUID so the total length stays well within the limit. String shortPrefix = prefix.length() > 12 ? prefix.substring(0, 12) : prefix; String shortUuid = UUID.randomUUID().toString().replace("-", "").substring(0, 16); - return "tb_at_" + shortPrefix + "_" + shortUuid; + String database = "tb_at_" + shortPrefix + "_" + shortUuid; + createdDatabases.add(database); + return database; } private TestAttributeKvEntry attr(long lastUpdateTs, String key, KvEntry value) { diff --git a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableIngestionBenchmarkIT.java b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableIngestionBenchmarkIT.java index 2ba0261..e0187b0 100644 --- a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableIngestionBenchmarkIT.java +++ b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableIngestionBenchmarkIT.java @@ -24,6 +24,7 @@ import org.apache.iotdb.isession.pool.ITableSessionPool; import org.apache.iotdb.session.pool.TableSessionPoolBuilder; import com.google.common.util.concurrent.ListenableFuture; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -79,6 +80,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Tag("integration") @Testcontainers(disabledWithoutDocker = true) class IoTDBTableIngestionBenchmarkIT { + private final List<String> createdDatabases = new ArrayList<>(); private static final Logger LOG = LoggerFactory.getLogger(IoTDBTableIngestionBenchmarkIT.class); // Smoke sizing: concurrency mirrors the TC-1 design (50 concurrent threads) but the total row @@ -402,10 +404,26 @@ class IoTDBTableIngestionBenchmarkIT { uniqueDatabase(), new TenantId(UUID.fromString("55555555-5555-5555-5555-555555555501"))); } + @AfterEach + void dropCreatedDatabases() throws Exception { + // Every test provisions its own database. Drop them once the test is done: the shared + // container has a fixed region memory budget, and leaving dozens of databases behind makes + // later tests in the class fail schema-region creation ("Total allocated memory for direct + // buffer ... is greater than limit mem cost") and time out on their first write. + try (ITableSessionPool pool = newPool(null); + ITableSession session = pool.getSession()) { + for (String database : createdDatabases) { + session.executeNonQueryStatement("DROP DATABASE IF EXISTS " + database); + } + } + } + private String uniqueDatabase() { // IoTDB caps database names at 64 chars; keep the prefix short and append a trimmed UUID. String shortUuid = UUID.randomUUID().toString().replace("-", "").substring(0, 16); - return "tb_bench_tc1_" + shortUuid; + String database = "tb_bench_tc1_" + shortUuid; + createdDatabases.add(database); + return database; } private static java.util.concurrent.ThreadFactory saverThreadFactory() { diff --git a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableLatestDaoIT.java b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableLatestDaoIT.java index cc00b4a..880ea2a 100644 --- a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableLatestDaoIT.java +++ b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableLatestDaoIT.java @@ -24,6 +24,7 @@ import org.apache.iotdb.isession.pool.ITableSessionPool; import org.apache.iotdb.session.pool.TableSessionPoolBuilder; import com.google.common.util.concurrent.ListenableFuture; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; @@ -64,6 +65,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Tag("integration") @Testcontainers(disabledWithoutDocker = true) class IoTDBTableLatestDaoIT { + private final List<String> createdDatabases = new ArrayList<>(); // Cold testcontainer first writes/reads are slower than a warm production node, so the // per-future assertion timeout is generous; production throughput is covered elsewhere. private static final int FUTURE_TIMEOUT_SECONDS = 30; @@ -1098,12 +1100,28 @@ class IoTDBTableLatestDaoIT { new TestEntityId(UUID.fromString(entityId), EntityType.DEVICE)); } + @AfterEach + void dropCreatedDatabases() throws Exception { + // Every test provisions its own database. Drop them once the test is done: the shared + // container has a fixed region memory budget, and leaving dozens of databases behind makes + // later tests in the class fail schema-region creation ("Total allocated memory for direct + // buffer ... is greater than limit mem cost") and time out on their first write. + try (ITableSessionPool pool = newPool(null); + ITableSession session = pool.getSession()) { + for (String database : createdDatabases) { + session.executeNonQueryStatement("DROP DATABASE IF EXISTS " + database); + } + } + } + private String uniqueDatabase(String prefix) { // IoTDB caps database names at 64 chars; keep the per-test prefix short and append a trimmed // UUID so the total length stays well within the limit. String shortPrefix = prefix.length() > 12 ? prefix.substring(0, 12) : prefix; String shortUuid = UUID.randomUUID().toString().replace("-", "").substring(0, 16); - return "tb_lt_" + shortPrefix + "_" + shortUuid; + String database = "tb_lt_" + shortPrefix + "_" + shortUuid; + createdDatabases.add(database); + return database; } private TestTsKvEntry entry(long ts, String key, DataType dataType, Object value) { diff --git a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesAggregationIT.java b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesAggregationIT.java index 97bc1ff..4bf100d 100644 --- a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesAggregationIT.java +++ b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesAggregationIT.java @@ -23,6 +23,7 @@ import org.apache.iotdb.isession.pool.ITableSessionPool; import org.apache.iotdb.session.pool.TableSessionPoolBuilder; import com.google.common.util.concurrent.ListenableFuture; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; @@ -67,6 +68,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Tag("integration") @Testcontainers(disabledWithoutDocker = true) class IoTDBTableTimeseriesAggregationIT { + private final List<String> createdDatabases = new ArrayList<>(); private static final int FUTURE_TIMEOUT_SECONDS = 30; private static final Duration IOTDB_STARTUP_TIMEOUT = Duration.ofMinutes(3); private static final Duration IOTDB_READY_TIMEOUT = Duration.ofSeconds(60); @@ -1111,10 +1113,26 @@ class IoTDBTableTimeseriesAggregationIT { new TestEntityId(UUID.fromString(entityId), EntityType.DEVICE)); } + @AfterEach + void dropCreatedDatabases() throws Exception { + // Every test provisions its own database. Drop them once the test is done: the shared + // container has a fixed region memory budget, and leaving dozens of databases behind makes + // later tests in the class fail schema-region creation ("Total allocated memory for direct + // buffer ... is greater than limit mem cost") and time out on their first write. + try (ITableSessionPool pool = newPool(null); + ITableSession session = pool.getSession()) { + for (String database : createdDatabases) { + session.executeNonQueryStatement("DROP DATABASE IF EXISTS " + database); + } + } + } + private String uniqueDatabase(String prefix) { String shortPrefix = prefix.length() > 12 ? prefix.substring(0, 12) : prefix; String shortUuid = UUID.randomUUID().toString().replace("-", "").substring(0, 16); - return "tb_it_" + shortPrefix + "_" + shortUuid; + String database = "tb_it_" + shortPrefix + "_" + shortUuid; + createdDatabases.add(database); + return database; } private TestTsKvEntry entry(long ts, String key, DataType dataType, Object value) { diff --git a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDaoIT.java b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDaoIT.java index 355fc4e..cc9bf77 100644 --- a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDaoIT.java +++ b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTimeseriesDaoIT.java @@ -25,6 +25,7 @@ import org.apache.iotdb.session.pool.TableSessionPoolBuilder; import com.google.common.util.concurrent.ListenableFuture; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -67,6 +68,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Tag("integration") @Testcontainers(disabledWithoutDocker = true) class IoTDBTableTimeseriesDaoIT { + private final List<String> createdDatabases = new ArrayList<>(); // Cold testcontainer first writes are slower than a warm production node, so the per-future // assertion timeout is generous; production throughput is covered elsewhere, not here. private static final int FUTURE_TIMEOUT_SECONDS = 30; @@ -630,12 +632,28 @@ class IoTDBTableTimeseriesDaoIT { new TestEntityId(UUID.fromString(entityId), EntityType.DEVICE)); } + @AfterEach + void dropCreatedDatabases() throws Exception { + // Every test provisions its own database. Drop them once the test is done: the shared + // container has a fixed region memory budget, and leaving dozens of databases behind makes + // later tests in the class fail schema-region creation ("Total allocated memory for direct + // buffer ... is greater than limit mem cost") and time out on their first write. + try (ITableSessionPool pool = newPool(null); + ITableSession session = pool.getSession()) { + for (String database : createdDatabases) { + session.executeNonQueryStatement("DROP DATABASE IF EXISTS " + database); + } + } + } + private String uniqueDatabase(String prefix) { // IoTDB caps database names at 64 chars; keep the per-test prefix short and // append a trimmed UUID so the total length stays well within the limit. String shortPrefix = prefix.length() > 12 ? prefix.substring(0, 12) : prefix; String shortUuid = UUID.randomUUID().toString().replace("-", "").substring(0, 16); - return "tb_it_" + shortPrefix + "_" + shortUuid; + String database = "tb_it_" + shortPrefix + "_" + shortUuid; + createdDatabases.add(database); + return database; } private int assertTelemetryRows( diff --git a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTtlIT.java b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTtlIT.java index 6fa7fb6..fde0ac7 100644 --- a/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTtlIT.java +++ b/iotdb-thingsboard-table/src/test/java/org/apache/iotdb/extras/thingsboard/table/IoTDBTableTtlIT.java @@ -23,6 +23,7 @@ import org.apache.iotdb.isession.SessionDataSet; import org.apache.iotdb.isession.pool.ITableSessionPool; import org.apache.iotdb.session.pool.TableSessionPoolBuilder; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; @@ -34,6 +35,7 @@ import org.testcontainers.utility.DockerImageName; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -61,6 +63,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Tag("integration") @Testcontainers(disabledWithoutDocker = true) class IoTDBTableTtlIT { + private final List<String> createdDatabases = new ArrayList<>(); private static final Duration IOTDB_STARTUP_TIMEOUT = Duration.ofMinutes(3); private static final Duration IOTDB_READY_TIMEOUT = Duration.ofSeconds(60); private static final Duration IOTDB_READY_POLL_INTERVAL = Duration.ofMillis(500); @@ -210,9 +213,25 @@ class IoTDBTableTtlIT { "IoTDB did not accept table-session statements within " + IOTDB_READY_TIMEOUT, lastFailure); } + @AfterEach + void dropCreatedDatabases() throws Exception { + // Every test provisions its own database. Drop them once the test is done: the shared + // container has a fixed region memory budget, and leaving dozens of databases behind makes + // later tests in the class fail schema-region creation ("Total allocated memory for direct + // buffer ... is greater than limit mem cost") and time out on their first write. + try (ITableSessionPool pool = newPool(null); + ITableSession session = pool.getSession()) { + for (String database : createdDatabases) { + session.executeNonQueryStatement("DROP DATABASE IF EXISTS " + database); + } + } + } + private String uniqueDatabase(String prefix) { String shortPrefix = prefix.length() > 12 ? prefix.substring(0, 12) : prefix; String shortUuid = UUID.randomUUID().toString().replace("-", "").substring(0, 16); - return "tb_it_" + shortPrefix + "_" + shortUuid; + String database = "tb_it_" + shortPrefix + "_" + shortUuid; + createdDatabases.add(database); + return database; } }
