Skip to main content

data

ClickHouse access for the kernel and modules (Architecture › Database). Everything a module needs to persist goes through Database; nothing else in the tree opens a socket to the database. Source in libs/data/.

Types​

TypeRole
DatabaseConfigURL, database name and credentials from SHATTERVEIL_DB_URL / _NAME / _USER / _PASSWORD, falling back to CLICKHOUSE_USER / CLICKHOUSE_PASSWORD (the names in deploy/clickhouse/.env). Only loopback URLs are accepted; the password never appears in toString()
DatabaseThe entry point: open(config), migrate(migrations), query(sql, params) → List<Row>, insert(table, rows) via AsyncWriter, ping(), close(). All calls are asynchronous (CompletableFuture) and never block the tick thread
RowOne JSONEachRow result: typed getters (requireUuid, requireLong, requireInstant, stringMap, …) with clear errors
MigrationV<n>__<name>.sql files listed in a module's db/migrations/<module>/migrations.list; applied once, in order, recorded in schema_migrations
AsyncWriterBatches inserts per table on a virtual thread; bounded queue, drops with a counter instead of blocking
DatabaseExceptionisUnavailable() separates "ClickHouse is down" (retry later) from "the query is wrong" (a bug)
modules.ModuleStateRepositoryThe kernel's module_state table (enabled/disabled flags that survive restarts)
player.PlayerRecord, player.PlayerRecordStoreThe players table: immutable, versioned records; inMemory() store for tests and for running without a database

Safety​

  • Identifiers are validated (Database.requireIdentifier) and parameters are bound through ClickHouse's {name:Type} syntax; nothing from a player is ever concatenated into SQL.
  • Only http://127.0.0.1 / http://localhost URLs are accepted — the database is never exposed.
  • No database configured → DatabaseConfig.fromEnv() is empty and every consumer falls back to memory, saying so once in the log.

Adding a table​

A module owns its tables and ships their schema:

  1. Put V<n>__<name>.sql files under src/main/resources/db/migrations/<module>/.
  2. List them in migrations.list in that directory.
  3. Apply them from onEnable through Database.migrate(...).

Applied migrations are recorded in shatterveil.schema_migrations, which the ClickHouse container creates on first start.

Tests​

DataLibraryTest covers configuration, identifier validation, row parsing, migration loading and PlayerRecord without a live ClickHouse. Integration against the real container (deploy/clickhouse/) is manual for now.