Skip to content

[v3] fix(runner): cache Microsoft profile/certificate fetches across bot connections - #72

Merged
Drownek merged 7 commits into
Drownek:v3-devfrom
monikon22:fix/69-microsoft-profile-cert-cache
Sep 6, 2026
Merged

Drownek merged 7 commits into
Drownek:v3-devfrom
monikon22:fix/69-microsoft-profile-cert-cache

Conversation

@monikon22

Copy link
Copy Markdown
Contributor

Related to #65/#68 — same test run, different bug. Later in a heavy run, tests started failing with Failed to obtain profile data for <account>, does the account own minecraft? even though the account is fine.

Root cause: every test gets its own bot connection (Session.createBotmineflayer.createBot), so a microsoft-auth account redoes the full Microsoft handshake every single test. prismarine-auth already disk-caches the MS/Xbox token itself (Authflow.getMinecraftJavaToken's verifyTokens() skips the network call when it's still valid), but fetchProfile()/fetchCertificates() run unconditionally on every connect with no caching of their own — straight to api.minecraftservices.com. Enough tests back to back and one of those calls hits a rate limit or a transient blip.

Fix: a custom auth function (microsoft-auth.ts) that mirrors minecraft-protocol's own microsoftAuth.authenticate (same defaults, same session/error shape) but caches the profile/certificates result per account username in memory, for the life of the run process, and only refetches them if that first fetch never succeeded. Access token is untouched — still requested every connect, since that part is already cheap.

Only the Microsoft handshake is affected. mineflayer.createBot() still runs fresh per test, so this doesn't reopen #53.

prismarine-auth moves from a transitive to a direct dependency of @plugwright/runner, since the custom auth function calls Authflow.getMinecraftJavaToken directly.

Verified with npm run typecheck; the package has no unit test suite to add a test to.

Fixes #69

monikon22 and others added 7 commits September 6, 2026 16:20
minecraft-protocol's built-in 'microsoft' auth refetches profile and
certificates on every connect, no caching of their own. Every test gets
its own bot connection, so a microsoft-auth account redoes that on
every single test; enough tests in one run and one of those calls
eventually hits a rate limit and fails a perfectly fine account.

Add a custom auth function (microsoft-auth.ts) that mirrors
minecraft-protocol's own microsoftAuth.authenticate but caches
fetchProfile/fetchCertificates results per username for the life of
the process. The access token itself is untouched — still fetched
per connect via prismarine-auth's own disk cache, which is already
cheap.

Needs prismarine-auth as a direct dependency now (was only transitive
through mineflayer) to call Authflow.getMinecraftJavaToken directly.
Session.createBot passed auth straight through as a string. Swap it
for the cached custom auth function (microsoft-auth.ts) whenever the
account is microsoft-auth; offline/mojang accounts are unaffected.

Fixes Drownek#69
'import { Authflow, Titles } from prismarine-auth' compiled fine but
crashed at runtime: 'SyntaxError: The requested module prismarine-auth
does not provide an export named Titles'. prismarine-auth is CJS;
Node's cjs-module-lexer interop for named ESM imports of a CJS module
isn't reliable here — it missed Titles even though both are plain
properties of module.exports.

Import the default (the whole module.exports object) instead and
destructure from that — the default import always works for CJS
interop.

Verified locally: typecheck, build, then imported the compiled
dist/lib/microsoft-auth.js directly with node. Caught only in CI, not
by tsc, since this is a runtime ESM/CJS interop quirk typecheck can't
see; this package has no local e2e harness to catch it earlier.
@Drownek

Drownek commented Sep 6, 2026

Copy link
Copy Markdown
Owner
  1. Almost every test was failing due to rcon bug, i've added a fix that adds a commandQueue, so that RCON commands are strictly serialized, preventing concurrent packets from corrupting the server's buffer and dropping the connection.

I also removed "sentinel strategy" for RCON i previously introduced. When RCON response is >4096 bytes, some servers split it into multiple packets, which the sentinel catches. However, our E2E tests never hit this limit, making the sentinel practically useless while it was actively triggering the concurrent packet crash.

  1. I noticed GitHub Actions passing green even though tests were failing with "RCON connection closed". Pushed a fix that properly sets process.exitCode before the process terminates, ensuring that test failures correctly result in a non-zero exit code and fail the Gradle build.

Merging, thanks

@Drownek
Drownek merged commit bea8b60 into Drownek:v3-dev Sep 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants