feat(lua): asobi_lua_match_shared bridge for encode-once broadcast#41
Merged
feat(lua): asobi_lua_match_shared bridge for encode-once broadcast#41
Conversation
Companion to asobi#117. Adds a thin bridge module that exports get_state/1 (shared-payload variant) and delegates everything else to asobi_lua_match. Selected by declaring `state_strategy = "shared"` in match.lua, which asobi_lua_config now reads and propagates to the mode config so asobi_game_modes resolves to this bridge. Lua scripts opting in must define one-arg `get_state(state)` returning the world view. The match server then JSON-encodes once per tick and broadcasts the same binary to every player (see asobi#117 for the broadcast-side change). Pin bump pending the upstream merge.
11 tasks
Taure
added a commit
that referenced
this pull request
May 5, 2026
) handle_input/3 in both asobi_lua_match and asobi_lua_world bridges no longer wraps the Luerl call in bounded_eval (spawn + monitor + heap_limit). At realistic input rates (200 players × 10 Hz = 2k inputs/sec) the per-call spawn overhead dominated actual Lua work and caused tail-latency stalls on the BEAM scheduler. Bench delta (asobi-bench, 200 bots, 30s, 10 Hz): - p99.9: ~2945ms -> ~1860ms (-37%) - max: ~3750ms -> ~2065ms (-45%) - inputs throughput: ~26k -> ~41k per 30s window (+56%) Trade-off documented in ADR 0002 and pinned by tests: - match_handle_input_no_wall_clock_timeout_test (match bridge) - world_handle_input_no_wall_clock_timeout_test (world bridge) - prop_lua_error_containment splits crash modes: tick still tests infinite_loop containment; input_crash_mode excludes it (would wedge the property runner — by design). Trust model updated in guides/security-trust-model.md with a new "Per-callback isolation" table and an explicit "handle_input is not a sandbox boundary" section. Also includes the project ADR convention (0000) and retroactive ADR 0001 documenting the asobi_lua_match_shared bridge that shipped in #41.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Companion to asobi#117.
asobi_lua_match_sharedbridge module that delegates init/join/leave/handle_input/tick/vote_* toasobi_lua_matchand exportsget_state/1calling Lua's one-argget_state(state)asobi_lua_configreads a newstate_strategyglobal from match.lua and addsstate_strategy => sharedto the mode config so asobi's resolver picks this bridgeLua scripts opt in by adding to match.lua:
```lua
state_strategy = "shared"
function get_state(state)
return { ... } -- one shared payload, no per-player view
end
```
Why
asobi#117 enables encode-once-per-tick broadcast for shared-state games via an optional
get_state/1callback. Static Erlang exports + Lua's lack of arity make a single dual-mode bridge awkward, so the cleanest expression is two bridge modules selected by a script-level flag. Existing{lua, Script}configs continue resolving toasobi_lua_match(per-player) — backward compatible.Test plan
rebar3 fmt --checkcleanrebar3 xrefcleanrebar3 dialyzerclean~/bin/elp eqwalize-allzero new errors (43 pre-existing)~/bin/elp lintzero new warnings on changed linesrebar3 eunit201/201 greenasobi_lua_match_shared_tests(init/lifecycle/get_state/1)state_strategy = "shared"end-to-end resolves toasobi_lua_match_shared