Debug APK Release
What's New
fix(api): harden decode boundaries and RpcEngine concurrency (#262)
ServerPlayer and ServerQueue declared required fields that the server
sometimes omits, and their enum fields (PlayerType, PlayerState,
RepeatMode) threw SerializationException on unknown wire variants.
Non-identity fields now carry safe defaults, and myJson opts into
coerceInputValues so unknown enum variants degrade to the default
(or null) instead of throwing. Answer.resultAs, Event.event, and
the ServerInfo handshake catch SerializationException at the decode
boundary so schema drift stays local to the affected RPC. Both
platforms benefit: on Kotlin/Native the uncaught exception aborted
the whole process, on JVM it would have killed the background
coroutine and dropped events.
RpcEngine.pendingResponses and partialResults were plain HashMaps
mutated from both the request-issuing coroutines and the websocket
message-collector coroutine. HashMap isn't concurrency-safe on
either platform; Kotlin/Native surfaced it as
ArrayIndexOutOfBoundsException out of HashMap#addKey, but the JVM
was latently vulnerable to the same bucket-array corruption. Both
maps are now AtomicReference with copy-on-write CAS updates,
matching the pattern already used elsewhere in the codebase.
Tests (commonTest, 35 new cases across five files) cover minimal
ServerPlayer/ServerQueue payloads, unknown enum coercion, list
decode surviving sparse entries, Answer/Event behaviour under
decode failure, plus two stress tests that hammer RpcEngine on
Dispatchers.Default to exercise the AtomicReference CAS loops.
Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com
Important Notes
- This is a debug build — not intended for production use
- Contains debug symbols and logging
- Performance may be slower than release builds
Installation
Download the APK below and install on your Android device.