Packages

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
game_server_sdk lib game_server kv.ex
Raw

lib/game_server/kv.ex

defmodule GameServer.KV do
@moduledoc ~S"""
Generic key/value storage.
This is intentionally minimal and un-opinionated.
If you want namespacing, encode it in `key` (e.g. `"polyglot_pirates:key1"`).
If you want per-user values, pass `user_id: ...` to `get/2`, `put/4`, and `delete/2`.
If you want per-lobby values, pass `lobby_id: ...` to the same functions.
You can also pass both to scope a key to a user within a lobby.
This module uses the app cache (`GameServer.Cache`) as a best-effort read cache.
Writes update the cache and deletes evict it.
**Note:** This is an SDK stub. Calling these functions will raise an error.
The actual implementation runs on the GameServer.
"""
@type list_opts() :: [
page: pos_integer(),
page_size: pos_integer(),
user_id: Ecto.UUID.t(),
lobby_id: Ecto.UUID.t(),
global_only: boolean(),
key: String.t()
]
@type attrs() :: %{
:key => String.t(),
optional(:user_id) => String.t(),
optional(:lobby_id) => String.t(),
:value => value(),
optional(:metadata) => metadata()
}
@type payload() :: %{value: value(), metadata: metadata()}
@type metadata() :: map()
@type value() :: map()
@doc ~S"""
Count the number of entries that match the optional filter.
Accepts the same options as `list_entries/1` (see `t:list_opts/0`). Returns a non-negative integer.
"""
@spec count_entries() :: non_neg_integer()
def count_entries() do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.KV.count_entries/0 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Count the number of entries that match the optional filter.
Accepts the same options as `list_entries/1` (see `t:list_opts/0`). Returns a non-negative integer.
"""
@spec count_entries(list_opts()) :: non_neg_integer()
def count_entries(_opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.KV.count_entries/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Create a new `Entry` from `attrs` (expecting `key`, optional `user_id`/`lobby_id`,
`value`, `metadata`).
Returns `{:ok, entry}` or `{:error, changeset}`.
"""
@spec create_entry(attrs()) :: {:ok, GameServer.KV.Entry.t()} | {:error, Ecto.Changeset.t()}
def create_entry(_attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.KV.create_entry/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Delete the entry at `key`.
Pass `user_id: id` or `lobby_id: id` in `opts` to delete a scoped key. Returns `:ok`.
"""
@spec delete(String.t()) :: :ok
def delete(_key) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.KV.delete/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Delete the entry at `key`.
Pass `user_id: id` or `lobby_id: id` in `opts` to delete a scoped key. Returns `:ok`.
"""
@spec delete(
String.t(),
keyword()
) :: :ok
def delete(_key, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.KV.delete/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Delete an entry by its `id`.
Returns `:ok` whether or not the entry existed.
"""
@spec delete_entry(pos_integer()) :: :ok
def delete_entry(_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.KV.delete_entry/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Retrieve the value and metadata stored for `key`.
Pass `user_id: id` or `lobby_id: id` in `opts` to scope the lookup.
Returns `{:ok, %{value: map(), metadata: map()}}` when found, or `:error` when not present.
"""
@spec get(String.t()) :: {:ok, payload()} | :error
def get(_key) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: :error, else: {:ok, %{value: %{}, metadata: %{}}}
_ ->
raise "GameServer.KV.get/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Retrieve the value and metadata stored for `key`.
Pass `user_id: id` or `lobby_id: id` in `opts` to scope the lookup.
Returns `{:ok, %{value: map(), metadata: map()}}` when found, or `:error` when not present.
"""
@spec get(
String.t(),
keyword()
) :: {:ok, payload()} | :error
def get(_key, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: :error, else: {:ok, %{value: %{}, metadata: %{}}}
_ ->
raise "GameServer.KV.get/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Fetch an `Entry` by its `id`.
Returns the `Entry` struct or `nil` if not found.
"""
@spec get_entry(Ecto.UUID.t()) :: GameServer.KV.Entry.t() | nil
def get_entry(_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.KV.get_entry/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List key/value entries with optional pagination and filtering.
Supported options: `:page`, `:page_size`, `:user_id`, `:lobby_id`, `:global_only`,
and `:key` (substring filter).
See `t:list_opts/0` for the expected option types.
Returns a list of `Entry` structs ordered by most recently updated.
"""
@spec list_entries() :: [GameServer.KV.Entry.t()]
def list_entries() do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.KV.list_entries/0 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
List key/value entries with optional pagination and filtering.
Supported options: `:page`, `:page_size`, `:user_id`, `:lobby_id`, `:global_only`,
and `:key` (substring filter).
See `t:list_opts/0` for the expected option types.
Returns a list of `Entry` structs ordered by most recently updated.
"""
@spec list_entries(list_opts()) :: [GameServer.KV.Entry.t()]
def list_entries(_opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.KV.list_entries/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Store `value` with optional `metadata` at `key`.
When using the 4-arity, supported options include `user_id: id` or `lobby_id: id` to scope
the entry.
Returns `{:ok, entry}` on success or `{:error, changeset}` on validation failure.
"""
@spec put(String.t(), value()) :: {:ok, GameServer.KV.Entry.t()} | {:error, Ecto.Changeset.t()}
def put(_key, _value) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.KV.put/2 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec put(String.t(), value(), metadata()) ::
{:ok, GameServer.KV.Entry.t()} | {:error, Ecto.Changeset.t()}
def put(_key, _value, _metadata) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.KV.put/3 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Store `value` with optional `metadata` at `key`.
When using the 4-arity, supported options include `user_id: id` or `lobby_id: id` to scope
the entry.
Returns `{:ok, entry}` on success or `{:error, changeset}` on validation failure.
"""
@spec put(String.t(), value(), metadata(), list_opts()) ::
{:ok, GameServer.KV.Entry.t()} | {:error, Ecto.Changeset.t()}
def put(_key, _value, _metadata, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.KV.put/4 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Subscribe the current process to changes for a specific key/scope.
"""
@spec subscribe(
String.t(),
keyword()
) :: :ok | {:error, term()}
def subscribe(_key, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.KV.subscribe/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Unsubscribe the current process from changes for a specific key/scope.
"""
@spec unsubscribe(
String.t(),
keyword()
) :: :ok | {:error, term()}
def unsubscribe(_key, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.KV.unsubscribe/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Update an existing entry by `id` with `attrs`.
Returns `{:ok, entry}`, `{:error, :not_found}` if missing, or `{:error, changeset}` on validation error.
"""
@spec update_entry(pos_integer(), attrs()) ::
{:ok, GameServer.KV.Entry.t()} | {:error, :not_found} | {:error, Ecto.Changeset.t()}
def update_entry(_id, _attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, nil}
_ ->
raise "GameServer.KV.update_entry/2 is a stub - only available at runtime on GameServer"
end
end
end