Skip to content

⚡ Eliminate runBlocking on main thread in command resolvers and fix HttpClient resource leaks #237

@Nlkomaru

Description

@Nlkomaru

Summary

Performance issues that can cause server lag during tab completion and resource exhaustion during long runs.

Issue 1: runBlocking on main thread in tab completion

Location:

  • paper/.../utils/command/resolver/RepositoryPluginParameterType.kt (lines 54-56, 76-78)
  • paper/.../utils/command/resolver/InstalledPluginParameterType.kt (lines 54-58, 77-81)
  • paper/.../utils/command/resolver/VersionSpecifierParameterType.kt (lines 67-74)

Both parse() and defaultSuggestions() use runBlocking which blocks the main server thread during tab completion. Network or disk I/O in these paths can cause visible server lag or TPS drops.

Fix: Pre-build an async cache of suggestions (refreshed periodically or on plugin state changes). Tab completion should read from memory-only cache, never from disk/network.

Issue 2: HttpClient created per-request and never closed

Location: paper/.../infrastructure/downloader/DownloaderRepositoryImpl.kt (lines 108-145, 232-245)

Each call to getLatestVersion(), getVersionByName(), getAllVersions(), and downloadByVersion() creates new instances of GithubDownloader, SpigotDownloader, ModrinthDownloader — each of which creates a new HttpClient. These clients are never closed, leaking threads and sockets.

Fix: Register a singleton HttpClient in Koin. Inject it into downloader instances. Close it in onDisable().

Issue 3: Entire JAR loaded into memory before writing to disk

Location: paper/.../infrastructure/downloader/AbstractPluginDownloader.kt (line 68)

tempFile.writeBytes(fileResponse.body())

The body() call loads the entire HTTP response into memory as a ByteArray. Large plugins (10+ MB) will cause unnecessary memory pressure.

Fix: Use bodyAsChannel() or streaming API to write directly to the temp file.

Impact

  • Server lag during tab completion (noticeable to players)
  • Thread/socket exhaustion over time (potential OOM or connection pool exhaustion)
  • Memory spikes during plugin downloads

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions