Interface StorageBackend

All Known Implementing Classes:
AbstractSqlStorage, MysqlStorage, PostgresStorage, SqliteStorage

public interface StorageBackend
The SQL half of the lazy-load + write-back cache model: the narrow contract CachedStorage needs from a database backend. The cache is authoritative for every owner it holds resident, so the backend is asked to read one player's rows on a cache miss (loadOwner(java.lang.String)), bulk-write dirty rows back (autosave / quit / shutdown), answer the few whole-database questions the cache cannot (findExpired(long), countChests(), findUuidByName(java.lang.String), loadAllPlayers() for the startup name index), snapshot itself for a backup, and receive the verbatim /ee import copy — there are deliberately no per-row write operations here; all row-level semantics live in CachedStorage.

All methods execute synchronously on the calling thread; callers keep them off region/main threads (cache-miss loads run on the DbExecutor, everything else on async timers or the shutdown flush).

  • Method Details

    • init

      void init()
      Creates schema, runs schema migrations, and prepares connections. Called once before anything else.
    • close

      void close()
      Closes all connections. Safe to call even if init() was not completed.
    • supportsBackup

      default boolean supportsBackup()
      True if this backend can produce a file snapshot via backup(Path). Only the file-based SQLite backend supports it; remote backends (MySQL/MariaDB/Postgres) return false and must be backed up with the database server's own tooling.
    • backup

      default void backup(Path target) throws Exception
      Writes a consistent snapshot of the entire database to target (which must not already exist). Only valid when supportsBackup() is true. The caller (CachedStorage) flushes dirty rows first, so the snapshot always contains every in-memory change.
      Throws:
      Exception - if the snapshot fails; the caller logs it and leaves the live DB untouched.
    • importRows

      Bulk-inserts raw players and enderchests rows verbatim into this (fresh) backend, in a single transaction — the DB→DB conversion primitive behind /ee import. A duplicate primary key (or any other failure) rolls the whole transaction back and throws.
      Returns:
      [playersInserted, chestsInserted]
    • loadAllPlayers

      Reads every players row verbatim. Used once at startup to build the in-memory PlayerNameIndex (uuid → username is tiny even for huge rosters); chest data is never bulk-loaded.
    • loadOwner

      StorageBackend.OwnerRows loadOwner(String playerUuid)
      Reads one player's enderchests rows and players row verbatim in a single connection acquisition (lazy cache load on first touch — the hottest backend read, so it must not pay for two pool round-trips).
    • findExpired

      List<StorageBackend.ExpiredKey> findExpired(long now)
      Keys of every row whose expires_at is set and at or before now. Candidates only: the caller re-verifies each hit against the authoritative in-memory row (which may be newer than what was last flushed here).
    • countChests

      long countChests()
      Total number of enderchests rows. The caller flushes first so pending changes count.
    • findUuidByName

      @Nullable @Nullable String findUuidByName(String name)
      Resolves a stored username to its UUID string, case-insensitively, or null when unknown. The caller checks resident (possibly renamed-but-unflushed) owners first.
    • flushDirty

      void flushDirty(List<EnderChestStorage.RawChestRow> chestUpserts, List<StorageBackend.ChestKey> chestDeletes, List<EnderChestStorage.RawPlayerRow> playerRows)
      Writes every dirty row back in one transaction: each chestUpserts / playerRows row replaces whatever the table holds for its key (native dialect upsert), and every chestDeletes key is removed. A single transaction and a single connection acquisition — the flush runs under the cache's flush lock, so its duration directly gates quit write-back latency. A failure rolls the whole flush back and throws, so the caller can re-mark the rows dirty and retry on the next autosave.