Skip to content

Architecture

shvquu edited this page Jun 16, 2026 · 3 revisions

Architecture

ServerDoctor follows a clean, layered design. The analysis core knows nothing about Bukkit or Velocity; platform adapters translate between the platform and the core. The boundaries are not just convention — they are enforced by ArchUnit tests that fail the build if violated.

Modules

Module Role
serverdoctor-common Domain models (PerformanceSnapshot, ConflictReport, Severity, …) and utilities
serverdoctor-api Public contract: ServerDoctorApi, events, the AnalysisModule SPI
serverdoctor-core Engine, the 5 scanners, recommendation engine, conflict database, update checker
serverdoctor-storage StorageProvider + 5 repositories; In-Memory, SQLite, PostgreSQL, MariaDB, MongoDB
serverdoctor-rest-api Read-only HTTP/JSON API (JDK HttpServer, no extra deps)
serverdoctor-webhook Discord/Slack/Teams notifications (JDK HttpClient, no extra deps)
serverdoctor-testing Fake-platform fixtures, JUnit 5 suite, ArchUnit rules
serverdoctor-paper Paper/Folia adapter, command, PlaceholderAPI bridge, storage wiring
serverdoctor-velocity Velocity adapter, command, storage wiring
serverdoctor-universal Shades Paper + Velocity into one jar

Platform abstraction

The core talks to a server only through small adapter interfaces (in com.serverdoctor.platform): scheduler, logger, metrics, plugins, players, command, execution context. Paper and Velocity each provide concrete implementations. Folia is handled by an alternate scheduler adapter selected at runtime.

Each scanner declares the capabilities it needs (HAS_PLUGINS, HAS_TICK_LOOP, …). The engine skips scanners whose capabilities the current platform doesn't offer — which is why the Performance scanner runs on servers but not on a proxy.

Storage boundary

The storage module is framework-free. The platform adapter reads its config source (Bukkit config on Paper, SnakeYAML-parsed config.yml on Velocity) and builds a plain StorageConfig, which StorageProviders turns into a concrete StorageProvider. No platform type ever enters the storage layer.

Enforced invariants (build breakers)

The ArchUnit rules in serverdoctor-testing fail the build if any of these are violated:

  • No platform SDK in Core, Common, API or Storage.
  • Clean-architecture dependency rule — inner layers never depend on outer ones.
  • Read-only platform adapters — adapters may observe the server but never mutate it.

Data flow

platform adapter ──▶ ServerContext (read-only)
                         │
                         ▼
                 AnalysisEngine ──▶ scanners ──▶ AnalysisResults
                         │                            │
                         ▼                            ▼
              RecommendationEngine            EventBus (API consumers)
                         │
                         ▼
                 DiagnosticReport ──▶ StorageProvider (history)

Clone this wiki locally