# =========================================================================== # Grim datastore # # Routes the DataStore categories (violation / session / player-identity / # setting / blob) to specific backend instances. Each backend listed in # `routing:` has its own settings file under `databases/.yml`. # # On first boot, if the legacy store (violations.sqlite) is present, it # is migrated into the new store automatically. Set migration.skip to # true if you prefer to carry over manually later. # =========================================================================== # Every datastore key lives under this top-level wrapper so the keyspace is # naturally namespaced — Configuralize merges every yml into one global # keyspace at runtime, and a flat layout here would collide with identical # top-level keys in config.yml / discord.yml (`enabled`, `history`, etc.). database: # Master toggle. Set false to disable violation history + /grim history # entirely. Live AC checks keep running; flags just aren't persisted. enabled: true # Categories → backend ids. Each distinct id here must have a matching # `databases/.yml` file (auto-created from bundled defaults on first # boot) and a registered BackendProvider at runtime. `none` disables # persistence for that category entirely. Mixed backends are fine — e.g. # violations in a networked SQL store and blobs in an object store. routing: violation: sqlite session: sqlite player-identity: sqlite setting: sqlite blob: none session: # Used at migration time only — the legacy V0 reader has no join/quit # signals, so SessionReconstructor groups violations into sessions when # consecutive flags fall within this gap. Live sessions are bounded by # the connection, not this value. gap-ms: 600000 scope-per-server: true # How often a connected-player heartbeat upserts the session row so # last_activity_epoch_ms stays current. Bounds the apparent session # duration if the server crashes (graceful disconnects always set # closed_at). Cost: ~one row UPSERT per online player per interval. # 0 disables. heartbeat-interval-ms: 30000 write-path: # queue-capacity must be a positive power of two (ring-buffer requirement). # Typical values: 4096, 8192, 16384, 32768, 65536. queue-capacity: 16384 batch-size: 256 flush-interval-ms: 1000 warn-rate-ms: 10000 shutdown-drain-timeout-ms: 5000 # Ring-buffer wait strategy. BLOCKING is the safe default: a condition-variable # wait that minimises CPU use at the cost of a small amount of latency under # extreme burst. Pick YIELDING or BUSY_SPIN only when you have a free core # budget and have measured a win over BLOCKING. # Options: BLOCKING, TIMEOUT_BLOCKING, SLEEPING, YIELDING, BUSY_SPIN. wait-strategy: BLOCKING retention: session: enabled: true max-age-days: 90 violation: enabled: true max-age-days: 365 player-identity: enabled: false setting: enabled: false blob: enabled: true max-age-days: 30 migration: skip: false max-duration-ms: 0 # 0 = no timeout name-resolution: # Order matters — first non-empty result wins. # local-cache reads the PlayerIdentity category. # offline-mode-uuid derives UUID.nameUUIDFromBytes (offline servers only). chain: [local-cache, offline-mode-uuid] history: entries-per-page: 15 group-interval-ms: 30000 # Display-only tag stamped on new session records. Shown in the session # header line of `/grim history`. Safe to change mid-operation. server-name: "Prison" # Schema markers — see header comment in config.yml. config-flavor: V2 config-version: 1