Packages
game_server_sdk
1.0.924
1.0.1082
1.0.1079
1.0.1078
1.0.1077
1.0.1076
1.0.1075
1.0.1074
1.0.1073
1.0.1070
1.0.1068
1.0.1067
1.0.1063
1.0.1059
1.0.1058
1.0.1057
1.0.1056
1.0.1055
1.0.1050
1.0.1049
1.0.1048
1.0.1047
1.0.1046
1.0.1044
1.0.1043
1.0.1042
1.0.1041
1.0.1040
1.0.1039
1.0.1038
1.0.1034
1.0.1033
1.0.1029
1.0.1028
1.0.1026
1.0.1025
1.0.1024
1.0.1023
1.0.1022
1.0.1021
1.0.1020
1.0.1019
1.0.1018
1.0.1017
1.0.1016
1.0.1015
1.0.1014
1.0.1013
1.0.1012
1.0.1011
1.0.1009
1.0.1008
1.0.1007
1.0.1006
1.0.1005
1.0.1004
1.0.1003
1.0.1001
1.0.999
1.0.998
1.0.997
1.0.996
1.0.995
1.0.994
1.0.993
1.0.992
1.0.991
1.0.990
1.0.989
1.0.988
1.0.987
1.0.986
1.0.985
1.0.984
1.0.983
1.0.982
1.0.981
1.0.980
1.0.979
1.0.978
1.0.977
1.0.976
1.0.975
1.0.974
1.0.973
1.0.972
1.0.971
1.0.970
1.0.969
1.0.968
1.0.967
1.0.966
1.0.965
1.0.964
1.0.963
1.0.962
1.0.961
1.0.959
1.0.958
1.0.956
1.0.951
1.0.950
1.0.943
1.0.942
1.0.941
1.0.940
1.0.938
1.0.936
1.0.935
1.0.931
1.0.929
1.0.928
1.0.927
1.0.926
1.0.925
1.0.924
1.0.923
1.0.921
1.0.920
1.0.919
1.0.918
1.0.917
1.0.916
1.0.911
1.0.910
1.0.902
1.0.899
1.0.898
1.0.897
1.0.896
1.0.894
1.0.893
1.0.891
1.0.890
1.0.889
1.0.888
1.0.887
1.0.886
1.0.885
1.0.884
1.0.883
1.0.882
1.0.881
1.0.880
1.0.879
1.0.878
1.0.877
1.0.26
1.0.25
1.0.22
1.0.21
1.0.20
1.0.19
1.0.15
1.0.14
1.0.13
1.0.12
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.1.0
SDK for GameServer hooks development. Provides type specs, documentation, and IDE autocomplete for GameServer modules without requiring the full server.
Current section
Files
Jump to
Current section
Files
lib/game_server/lock.ex
defmodule GameServer.Lock do
@moduledoc ~S"""
Serialized execution using database-level advisory locks.
Wraps a function in a `Repo.transaction` with an advisory lock so that
only one process at a time can execute the critical section for a given
`(namespace, resource_id)` pair.
This is useful for game RPCs where multiple players may trigger the same
operation concurrently (e.g. guessing a word, claiming a reward) and the
logic involves read-modify-write on KV entries or lobby metadata.
## How it works
On **PostgreSQL**, the lock is acquired via `pg_advisory_xact_lock` and is
automatically released when the transaction commits or rolls back. Other
callers with the same key block until the lock is available.
On **SQLite** (dev/test), advisory locks are a no-op because SQLite already
serializes all writes at the database level.
## Multi-node safety
Because the lock lives in the database, it works correctly across multiple
application nodes — all nodes share the same Postgres instance, so the lock
is globally consistent.
## Namespace conventions
The `namespace` argument can be:
- A **predefined atom**: `:lobby` (1), `:group` (2), `:party` (3)
- An **arbitrary string**: hashed to a stable integer, e.g. `"word_guessed"`
The `resource_id` is typically the lobby, group, or user id that scopes
the lock.
## Examples
# Serialize all "word_guessed" RPCs per lobby
GameServer.Lock.serialize("word_guessed", lobby_id, fn ->
{:ok, entry} = GameServer.KV.get("game_state", lobby_id: lobby_id)
new_val = Map.update(entry.value, "guessed", [word], &[word | &1])
GameServer.KV.put("game_state", new_val, %{}, lobby_id: lobby_id)
end)
# Using a predefined atom namespace
GameServer.Lock.serialize(:lobby, lobby_id, fn ->
# exclusive per-lobby operation
end)
## Return value
Returns `{:ok, result}` where `result` is the return value of the function,
or `{:error, reason}` if the transaction rolls back.
**Note:** This is an SDK stub. Calling these functions will raise an error.
The actual implementation runs on the GameServer.
"""
@doc ~S"""
Execute `fun` inside a transaction with an advisory lock on `(namespace, resource_id)`.
Only one process at a time can hold the lock for a given key pair. Other
callers block until the lock is released (on transaction commit/rollback).
Returns `{:ok, result}` on success or `{:error, reason}` on rollback.
## Parameters
- `namespace` — atom (`:lobby`, `:group`, `:party`) or any string
- `resource_id` — integer identifying the specific resource (e.g. lobby id)
- `fun` — zero-arity function to execute while holding the lock
"""
@spec serialize(atom() | String.t(), integer(), (-> result)) :: {:ok, result} | {:error, term()}
when result: term()
def serialize(_namespace, _resource_id, _fun) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Lock.serialize/3 is a stub - only available at runtime on GameServer"
end
end
end