Remove joined_rooms table

This commit is contained in:
Pim Kunis 2021-09-08 14:22:40 +02:00
parent 46b4199618
commit b12872fe2c
5 changed files with 23 additions and 74 deletions

View file

@ -19,7 +19,6 @@ defmodule Architex.RoomServer do
Event, Event,
StateResolution, StateResolution,
Account, Account,
JoinedRoom,
Device, Device,
DeviceTransaction, DeviceTransaction,
Membership Membership
@ -606,8 +605,6 @@ defmodule Architex.RoomServer do
room = Room.update_forward_extremities(event, room) room = Room.update_forward_extremities(event, room)
event = Repo.insert!(event) event = Repo.insert!(event)
state_set = StateResolution.resolve_forward_extremities(event) state_set = StateResolution.resolve_forward_extremities(event)
# TODO: Do this as a background job, and not after every insert...
_ = update_joined_rooms(room, state_set)
:ok = update_membership(room, state_set) :ok = update_membership(room, state_set)
{:ok, state_set, room, event} {:ok, state_set, room, event}
@ -616,45 +613,11 @@ defmodule Architex.RoomServer do
end end
end end
# Update local accounts' room membership if applicable. # TODO: Might be better to calculate membership changes only...
@spec update_joined_rooms(Room.t(), t()) :: JoinedRoom.t() | nil # TODO: I don't think this should be a background job, as it get out-of-sync and users
defp update_joined_rooms(%Room{id: room_id}, state_set) do # could access rooms they are not allowed to. Then again, maybe we should perform
server_name = Architex.server_name() # the "normal" authorization flow for local users as well, and treat the Membership
# table only as informational.
{joined, not_joined} =
state_set
|> Enum.filter(fn {{type, state_key}, _} ->
type == "m.room.member" and Architex.get_domain(state_key) == server_name
end)
|> Enum.split_with(fn {_, %Event{content: %{"membership" => membership}}} ->
membership == "join"
end)
map_localparts =
&Enum.map(&1, fn {{_, state_key}, _} -> Architex.get_localpart(state_key) end)
joined_localparts = map_localparts.(joined)
not_joined_localparts = map_localparts.(not_joined)
_ =
Repo.insert_all(
JoinedRoom,
from(a in Account,
where: a.localpart in ^joined_localparts,
select: %{account_id: a.id, room_id: ^room_id}
),
on_conflict: :nothing
)
Repo.delete_all(
from jr in JoinedRoom,
join: a in Account,
on: a.id == jr.account_id,
where: jr.room_id == ^room_id and a.localpart in ^not_joined_localparts
)
end
# TODO: Might be better to calculate membership changes...
@spec update_membership(Room.t(), t()) :: :ok @spec update_membership(Room.t(), t()) :: :ok
defp update_membership(%Room{id: room_id}, state_set) do defp update_membership(%Room{id: room_id}, state_set) do
server_name = Architex.server_name() server_name = Architex.server_name()

View file

@ -3,7 +3,7 @@ defmodule Architex.Account do
import Ecto.{Changeset, Query} import Ecto.{Changeset, Query}
alias Architex.{Repo, Account, Device, Room, JoinedRoom} alias Architex.{Repo, Account, Device, Room, Membership}
alias ArchitexWeb.Client.Request.{Register, Login} alias ArchitexWeb.Client.Request.{Register, Login}
alias Ecto.{Multi, Changeset} alias Ecto.{Multi, Changeset}
@ -19,8 +19,19 @@ defmodule Architex.Account do
has_many :devices, Device has_many :devices, Device
many_to_many :joined_rooms, Room, many_to_many :joined_rooms, Room,
join_through: JoinedRoom, join_through: Membership,
join_keys: [account_id: :id, room_id: :id] join_keys: [account_id: :id, room_id: :id],
join_where: [membership: "join"]
many_to_many :invited_rooms, Room,
join_through: Membership,
join_keys: [account_id: :id, room_id: :id],
join_where: [membership: "invite"]
many_to_many :left_rooms, Room,
join_through: Membership,
join_keys: [account_id: :id, room_id: :id],
join_where: [membership: "leave"]
timestamps(updated_at: false) timestamps(updated_at: false)
end end

View file

@ -1,17 +0,0 @@
defmodule Architex.JoinedRoom do
use Ecto.Schema
alias Architex.{Account, Room}
@type t :: %__MODULE__{
account_id: integer(),
room_id: String.t()
}
@primary_key false
schema "joined_rooms" do
belongs_to :account, Account, primary_key: true
belongs_to :room, Room, primary_key: true, type: :string
end
end

View file

@ -4,7 +4,7 @@ defmodule ArchitexWeb.Client.SyncController do
import ArchitexWeb.Error import ArchitexWeb.Error
import Ecto.Query import Ecto.Query
alias Architex.{Repo, Event, Account, Room, JoinedRoom} alias Architex.{Repo, Event, Account, Room, Membership}
alias Plug.Conn alias Plug.Conn
@doc """ @doc """
@ -26,10 +26,10 @@ defmodule ArchitexWeb.Client.SyncController do
events_per_room = events_per_room =
Event Event
|> join(:inner, [e], jr in JoinedRoom, |> join(:inner, [e], m in Membership,
on: jr.room_id == e.room_id and jr.account_id == ^account_id on: m.room_id == e.room_id and m.account_id == ^account_id and m.membership == "join"
) )
|> join(:inner, [e, jr], r in Room, on: r.id == jr.room_id) |> join(:inner, [e, m], r in Room, on: r.id == m.room_id)
|> order_by(asc: :origin_server_ts, asc: :nid) |> order_by(asc: :origin_server_ts, asc: :nid)
|> Repo.all() |> Repo.all()
|> Enum.group_by(& &1.room_id) |> Enum.group_by(& &1.room_id)

View file

@ -17,14 +17,6 @@ defmodule Architex.Repo.Migrations.CreateInitialTables do
add :visibility, :string, null: false, default: "public" add :visibility, :string, null: false, default: "public"
end end
create table(:joined_rooms, primary_key: false) do
add :account_id, references(:accounts), primary_key: true, null: false
add :room_id, references(:rooms, type: :string),
primary_key: true,
null: false
end
create table(:events, primary_key: false) do create table(:events, primary_key: false) do
add :nid, :serial, primary_key: true add :nid, :serial, primary_key: true
add :id, :string, null: false add :id, :string, null: false