Skip to content
Bluetape4k docs1.11

Operational boundaries and Testcontainers verification

Latest stable Based on Bluetape4k release 1.11.0

CassandraAdmin is not only a collection of read helpers. createKeyspace and dropKeyspace change schema, while getReleaseVersion reads system.local.

import io.bluetape4k.cassandra.CassandraAdmin
val created = CassandraAdmin.createKeyspace(
session = adminSession,
keyspace = "orders",
replicationFactor = 1,
)
val version = CassandraAdmin.getReleaseVersion(adminSession)

createKeyspace uses CREATE KEYSPACE IF NOT EXISTS with SimpleStrategy; its default replication factor is 1. That default is convenient for local examples but is not a replacement for production topology and replication policy. In production, it is usually safer for deployment tooling to create the keyspace and for the application to consume it.

dropKeyspace executes DROP KEYSPACE IF EXISTS synchronously. It is useful for test cleanup, but a wrong keyspace removes all of its data. Do not pass user input directly, and do not grant the application schema privileges it does not need.

In 1.11.0, CqlSessionProvider first opens an admin session so that it can create the target keyspace. The admin session comes from the builder returned by builderSupplier; the trailing builder block applies only to the final session. Put the contact point, localDatacenter, authentication, and TLS settings required by bootstrap in builderSupplier.

val session = CqlSessionProvider.getOrCreateSession(
identity = identity,
builderSupplier = {
CqlSessionProvider.newCqlSessionBuilder(contactPoint, localDatacenter)
.withAuthCredentials(username, password)
},
) {
withApplicationName("order-reader")
}

The admin account needs permission to create the keyspace. If the application account cannot receive that permission, or admin and workload connections require different settings, manage the keyspace during deployment and open a directly owned session. This is the behavior before the bootstrap-builder fix merged after 1.11.0.

Keep enough logs and metrics to distinguish the failure boundary without exposing data.

BoundaryObserve
Keyspace administrationOperation, approved keyspace, replication settings, wasApplied, exception
Session creationSafe target alias, local datacenter, opaque configuration IDs in the identity
Query executionQuery shape, consistency, timeout, success, failure, cancellation
PagingRows/pages consumed, mapper failure, next-page fetch failure, collection cancellation
BatchBatch type, partition scope, statement count, payload, latency, timeout
ShutdownDirect/provider ownership, close start/completion, in-flight work

Version 1.11.0 logs CqlSessionIdentity.context at INFO when creating a session. Do not put passwords, tokens, raw user, tenant, or customer identifiers in the context. Request IDs and random UUIDs also create unbounded cache identities. Use only a bounded set of log-approved routing profile IDs or credential versions.

Logging bound query values can expose personal data or credentials. Prefer query shape and marker names for diagnosis, and apply the application’s redaction policy to actual values.

SymptomFirst boundary to check
Bootstrap authentication or connection failureConfirm that builderSupplier contains the settings required by the 1.11.0 admin session
Wrong session reused for the same keyspaceConfirm that CqlSessionIdentity context includes the connection/tenant boundary
Flow returns only some rowsCheck collection cancellation, mapper exception, and next-page fetch failure
Connections remain after shutdownSeparate shutdown ownership for direct and provider-owned sessions
Batch latency or timeoutCheck partition scope, statement count, consistency, and timeout

When only some rows were observed, do not assume that asFlow accumulates the full result atomically. Rows emitted before a mapper or collector failure may already have been processed. A next-page fetch failure surfaces only after the current page is exhausted.

Close directly created sessions with use or close. Provider-created sessions are shared resources registered in ShutdownQueue; do not wrap ordinary uses in use. Before explicitly closing one, stop new users of that identity and wait for in-flight work. The provider has no atomic retire or evict API.

The module tests use Testcontainers where real Cassandra behavior matters.

Terminal window
./gradlew :bluetape4k-cassandra:test --no-build-cache --no-configuration-cache

The command requires a working Docker runtime and permission to pull or run the Cassandra image. Run it sequentially with other heavy Testcontainers tests because they share containers, ports, CPU, and disk. Report daemon connection, image pull, and startup timeout failures separately from assertion failures, but do not count them as success.

AbstractCassandraTest opens a Cassandra 4 container session, closes it in @AfterAll, and uses SAME_THREAD. CassandraAdminTest covers create/drop/version and blank-keyspace rejection. CqlSessionProviderTest covers identity reuse and connection-context separation. AsyncResultSetSupportTest inserts 6,000 rows and verifies that plain and mapped rows are collected across pages.

Start with the closest test when reproducing an incident, then use the module command above for final verification. Passing only mock-based tests does not prove authentication, schema permissions, paging, or container lifecycle.