asobi_world_lobby_server (asobi v0.35.4)

View Source

Single point of serialization for asobi_world_lobby:find_or_create/1.

The naive find_or_create implementation has a TOCTOU race: two clients calling at the same time both see list_worlds(...) = [] because neither has finished create_world/1 yet, and both end up spawning a new world for the same mode. Customer-visible symptom: two players opening barrow at the same instant land in different hub worlds and never see each other.

This gen_server forces all find_or_create calls through a single process. The handler runs the existing list_worlds + create_world sequence atomically with respect to other callers, so the second caller sees the world the first one just spawned.

Calls are sequential, but create_world/1 is the slowest step and takes <100ms in practice; for the small number of distinct modes a typical deployment supports, the queue stays empty.

Summary

Functions

Atomic version of asobi_world_lobby:find_or_create/1. Public callers should always go through this — calling the inner function directly is racy.

Functions

find_or_create(Mode)

-spec find_or_create(binary()) -> {ok, pid(), map()} | {error, term()}.

Atomic version of asobi_world_lobby:find_or_create/1. Public callers should always go through this — calling the inner function directly is racy.

find_or_create(Mode, PlayerId)

-spec find_or_create(binary(), binary() | undefined) -> {ok, pid(), map()} | {error, term()}.

handle_call/3

-spec handle_call(term(), gen_server:from(), map()) -> {reply, term(), map()}.

handle_cast(Msg, State)

-spec handle_cast(term(), map()) -> {noreply, map()}.

init/1

-spec init([]) -> {ok, #{}}.

start_link()

-spec start_link() -> gen_server:start_ret().