A foreign key violation was causing the server to never delete stale
rooms during `Database::refresh_room` due to having one or more project
records referencing the room.
Previously anyone unfollowing someone would clear all other rows for
other followers leading to an incorrect state, fix and test
Co-Authored-By: Max Brunsfeld <max@zed.dev>
Previously, when the host repeatedly sent `UpdateWorktree` messages,
new guests attempting to join a project would observe a severe slowdown
caused by a database serialization error (e.g., the coherence of the data
would get violated midway through `Database::join_project` due to worktree
entries being mutated as the user joined). Writing entries is pretty fast,
whereas reading all of them for a project can take more than 100ms.
Transactions that failed due to a serialization error are retried, but the guest
would keep retrying until the host finished writing because the guest's read
was slow.
This commit changes the semantics of `room_transaction` to acquire a room
lock before even starting the transaction and holding it all the way after
commit (storing it, as before, in the `RoomGuard`). This ensures that a fast
writer (the host) can't starve a slow reader (the guest), allowing the latter
to make progress by temporarily pausing writes by the former.
Previously, when initiating a call by calling multiple people, only
the first person would get the call while all the others would briefly
show a "pending" status but never get the call.
This would happen because `ActiveCall` was trying to a create a different
room for each person called, because the original room creation hadn't finished
and so a `ModelHandle<Room>` wasn't being store in the active call.
With this commit, only one room can be created at any given time and further
invites have to wait until that room creation is done.
Previously, if a user temporarily disconnected while there was a pending
call, we would fail to cancel such pending call when the caller left the
room. This was due to the caller reconnecting and having a different connection
id than the one originally used to initiate the call.
When we ask the server to remove a contact we need to push the requester and responder ids to `remove_contacts` so that when the UI updates, the correct contacts will disappear from the list.
Co-Authored-By: Antonio Scandurra <me@as-cii.com>