WIP room server

This commit is contained in:
Pim Kunis 2021-07-21 15:50:28 +02:00
parent 8919fe3f14
commit 2d34f78a0b
2 changed files with 99 additions and 9 deletions

View file

@ -111,16 +111,19 @@ defmodule MatrixServer.Event do
room: %Room{id: room_id} room: %Room{id: room_id}
}) do }) do
# TODO: state resolution # TODO: state resolution
create_room(room_id, MatrixServer.get_mxid(localpart), room_version) create_room_event = create_room(room_id, MatrixServer.get_mxid(localpart), room_version)
|> repo.insert() resolve([events_to_state_set([create_room_event])])
repo.insert(create_room_event)
end end
def room_creation_join_creator(repo, %{ def room_creation_join_creator(repo, %{
room: %Room{id: room_id}, room: %Room{id: room_id},
create_room_event: %Event{sender: creator} create_room_event: %Event{sender: creator, event_id: create_room_id}
}) do }) do
# TODO: state resolution # TODO: state resolution
join(room_id, creator) join(room_id, creator)
|> Map.put(:prev_events, [create_room_id])
|> Map.put(:auth_events, [create_room_id])
|> repo.insert() |> repo.insert()
end end
@ -128,46 +131,130 @@ defmodule MatrixServer.Event do
repo, repo,
%{ %{
room: %Room{id: room_id}, room: %Room{id: room_id},
create_room_event: %Event{sender: creator} create_room_event: %Event{sender: creator, event_id: create_room_id},
join_creator_event: %Event{event_id: join_creator_id}
} }
) do ) do
# TODO: state resolution # TODO: state resolution
power_levels(room_id, creator) power_levels(room_id, creator)
|> Map.put(:prev_events, [join_creator_id])
|> Map.put(:auth_events, [create_room_id, join_creator_id])
|> repo.insert() |> repo.insert()
end end
def room_creation_name(_repo, %{input: %CreateRoom{name: nil}}), do: {:ok, :noop} def room_creation_name(_repo, %{input: %CreateRoom{name: nil}}), do: {:ok, nil}
def room_creation_name(_repo, %{input: %CreateRoom{name: name}}) when byte_size(name) > 255,
do: {:error, :name}
def room_creation_name( def room_creation_name(
repo, repo,
%{ %{
input: %CreateRoom{name: name}, input: %CreateRoom{name: name},
room: %Room{id: room_id}, room: %Room{id: room_id},
create_room_event: %Event{sender: creator} create_room_event: %Event{sender: creator, event_id: create_room_id},
join_creator_event: %Event{event_id: join_creator_id},
power_levels_event: %Event{event_id: power_levels_id}
} }
) do ) do
# TODO: state resolution # TODO: state resolution
# TODO: check name length
room_name(room_id, creator, name) room_name(room_id, creator, name)
|> Map.put(:prev_events, [power_levels_id])
|> Map.put(:auth_events, [create_room_id, join_creator_id, power_levels_id])
|> repo.insert() |> repo.insert()
end end
def room_creation_topic(_repo, %{input: %CreateRoom{topic: nil}}), do: {:ok, :noop} def room_creation_topic(_repo, %{input: %CreateRoom{topic: nil}}), do: {:ok, nil}
def room_creation_topic( def room_creation_topic(
repo, repo,
%{ %{
input: %CreateRoom{topic: topic}, input: %CreateRoom{topic: topic},
room: %Room{id: room_id}, room: %Room{id: room_id},
create_room_event: %Event{sender: creator} create_room_event: %Event{sender: creator, event_id: create_room_id},
join_creator_event: %Event{event_id: join_creator_id},
power_levels_event: %Event{event_id: power_levels_id},
name_event: name_event
} }
) do ) do
# TODO: state resolution # TODO: state resolution
prev_event = if name_event, do: name_event.event_id, else: power_levels_id
room_topic(room_id, creator, topic) room_topic(room_id, creator, topic)
|> Map.put(:prev_events, [prev_event])
|> Map.put(:auth_events, [create_room_id, join_creator_id, power_levels_id])
|> repo.insert() |> repo.insert()
end end
def generate_event_id do def generate_event_id do
"$" <> MatrixServer.random_string(17) <> ":" <> MatrixServer.server_name() "$" <> MatrixServer.random_string(17) <> ":" <> MatrixServer.server_name()
end end
def events_to_state_set(events) do
Enum.into(events, %{}, fn %Event{type: type, state_key: state_key} = event ->
{{type, state_key}, event}
end)
end
def resolve(state_sets) do
{unconflicted_state_map, conflicted_set} = calculate_conflict(state_sets)
# full_conflicted_set = MapSet.union(conflicted_set, auth_difference(state_sets))
# conflicted_control_events =
# Enum.filter(full_conflicted_set, &is_control_event/1) |> MapSet.new()
# conflicted_control_events_with_auth =
# MapSet.union(
# conflicted_control_events,
# MapSet.intersection(
# full_conflicted_set,
# full_auth_chain(MapSet.to_list(conflicted_control_events))
# )
# )
# sorted_control_events = Enum.sort(conflicted_control_events_with_auth, &rev_top_pow_order/2)
# partial_resolved_state = iterative_auth_checks(sorted_control_events, unconflicted_state_map)
# other_conflicted_events =
# MapSet.difference(full_conflicted_set, conflicted_control_events_with_auth)
# resolved_power_levels = partial_resolved_state[{:power_levels, ""}]
# sorted_other_events =
# Enum.sort(other_conflicted_events, mainline_order(resolved_power_levels))
# nearly_final_state = iterative_auth_checks(sorted_other_events, partial_resolved_state)
# Map.merge(nearly_final_state, unconflicted_state_map)
end
def calculate_conflict(state_sets) do
{unconflicted, conflicted} =
state_sets
|> Enum.flat_map(&Map.keys/1)
|> MapSet.new()
|> Enum.map(fn state_pair ->
events =
Enum.map(state_sets, &Map.get(&1, state_pair))
|> MapSet.new()
{state_pair, events}
end)
|> Enum.split_with(fn {_k, events} ->
MapSet.size(events) == 1
end)
unconflicted_state_map = Enum.into(unconflicted, %{}, fn {state_pair, events} ->
event = MapSet.to_list(events) |> hd()
{state_pair, event}
end)
conflicted_state_set = Enum.reduce(conflicted, MapSet.new(), fn {_, events}, acc ->
MapSet.union(acc, events)
end)
|> MapSet.delete(nil)
{unconflicted_state_map, conflicted_state_set}
end
end end

View file

@ -31,6 +31,9 @@ defmodule MatrixServer.RoomServer do
|> Multi.run(:power_levels_event, &Event.room_creation_power_levels/2) |> Multi.run(:power_levels_event, &Event.room_creation_power_levels/2)
|> Multi.run(:name_event, &Event.room_creation_name/2) |> Multi.run(:name_event, &Event.room_creation_name/2)
|> Multi.run(:topic_event, &Event.room_creation_topic/2) |> Multi.run(:topic_event, &Event.room_creation_topic/2)
|> Multi.run(:temp, fn _, _ ->
{:error, :lol}
end)
|> Repo.transaction() |> Repo.transaction()
{:reply, result, state} {:reply, result, state}