Skip to content

Commit a740bf0

Browse files
committed
Enhances server user state consistency; upgrades C#
Refactors the `InMemoryRoomManager` to store only user IDs per connection, ensuring that all user-specific operations consistently retrieve the latest `User` object from the active `RoomState`. This prevents potential desynchronization issues. Upgrades the project to C# 13, enabling new language features and adopting modern collection expression syntax. Removes direct user update calls from client view models and adjusts available voting options.
1 parent 6fc7c8c commit a740bf0

File tree

5 files changed

+23
-28
lines changed

5 files changed

+23
-28
lines changed

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<PropertyGroup>
33
<Nullable>enable</Nullable>
44
<ImplicitUsings>enable</ImplicitUsings>
5+
<LangVersion>13</LangVersion>
56
</PropertyGroup>
67

78
<ItemGroup>

PointerStar/Client/Components/UserDialog.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@
4747
private void Submit() => MudDialog?.Close(DialogResult.Ok(ViewModel));
4848
private void Cancel() => MudDialog?.Cancel();
4949

50-
protected override async Task OnParametersSetAsync()
51-
{
50+
protected override async Task OnParametersSetAsync()
51+
{
5252
await base.OnParametersSetAsync();
5353
ViewModel.Name = Name;
5454
ViewModel.SelectedRoleId = SelectedRoleId;

PointerStar/Client/ViewModels/UserDialogViewModel.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ public UserDialogViewModel(HttpClient httpClient, IRoomHubConnection roomHubConn
2222
public void SelectRole(Role? role)
2323
{
2424
SelectedRoleId = role?.Id;
25-
if(RoomHubConnection.IsConnected)
26-
{
27-
RoomHubConnection.UpdateUserAsync(new UserOptions { Name = Name, Role = role });
28-
}
2925
}
3026

3127
public async Task LoadRoomDataAsync(string? roomId)

PointerStar/Server/Room/InMemoryRoomManager.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ public class InMemoryRoomManager : IRoomManager
66
private ConcurrentDictionary<string, SemaphoreSlim> RoomLocks { get; } = new();
77
private ConcurrentDictionary<string, RoomState> Rooms { get; } = new();
88
private ConcurrentDictionary<string, string> ConnectionsToRoom { get; } = new();
9-
private ConcurrentDictionary<string, User> ConnectionsToUser { get; } = new();
9+
private ConcurrentDictionary<string, Guid> ConnectionsToUserId { get; } = new();
1010

1111
public Task<RoomState> AddUserToRoomAsync(string roomId, User user, string connectionId)
1212
{
1313
ConnectionsToRoom.AddOrUpdate(connectionId, roomId, (_, _) => roomId);
14-
ConnectionsToUser.AddOrUpdate(connectionId, user, (_, _) => user);
14+
ConnectionsToUserId.AddOrUpdate(connectionId, user.Id, (_, _) => user.Id);
1515

1616
if (user.Name.Length > User.MaxNameLength)
1717
{
@@ -21,14 +21,14 @@ public Task<RoomState> AddUserToRoomAsync(string roomId, User user, string conne
2121
return WithRoomLock(roomId, () =>
2222
{
2323
RoomState rv = Rooms.AddOrUpdate(roomId,
24-
new RoomState(roomId, new[] { user }),
24+
new RoomState(roomId, [user]),
2525
(_, roomState) =>
2626
{
2727
return roomState with
2828
{
29-
Users = roomState.Users
29+
Users = [..roomState.Users
3030
.Where(u => u.Id != user.Id)
31-
.Append(user).ToArray()
31+
.Append(user)]
3232
};
3333
});
3434
return Task.FromResult(rv);
@@ -40,8 +40,8 @@ public Task<RoomState> AddUserToRoomAsync(string roomId, User user, string conne
4040
{
4141
return WithConnection(connectionId, (room, currentUser) =>
4242
{
43-
User[] users = room.Users.Where(x => x.Id != currentUser.Id).ToArray();
44-
if (users.Any())
43+
User[] users = [..room.Users.Where(x => x.Id != currentUser.Id)];
44+
if (users.Length != 0)
4545
{
4646
return room with { Users = users };
4747
}
@@ -83,7 +83,7 @@ public Task<RoomState> AddUserToRoomAsync(string roomId, User user, string conne
8383
{
8484
return WithConnection(connectionId, (room, currentUser) =>
8585
{
86-
User[] users = room.Users.Select(x =>
86+
User[] users = [..room.Users.Select(x =>
8787
{
8888
if (x.Id == currentUser.Id)
8989
{
@@ -101,7 +101,7 @@ public Task<RoomState> AddUserToRoomAsync(string roomId, User user, string conne
101101
}
102102
}
103103
return x;
104-
}).ToArray();
104+
})];
105105
return room with { Users = users };
106106
});
107107
}
@@ -116,11 +116,11 @@ public Task<RoomState> AddUserToRoomAsync(string roomId, User user, string conne
116116
}
117117
var roomState = room with
118118
{
119-
Users = room.Users.Select(u => u.Id == currentUser.Id ? u with
119+
Users = [..room.Users.Select(u => u.Id == currentUser.Id ? u with
120120
{
121121
OriginalVote = room.VotesShown ? u.OriginalVote : vote,
122122
Vote = vote
123-
} : u).ToArray()
123+
} : u)]
124124
};
125125

126126
if (ShouldShowVotes(roomState))
@@ -187,20 +187,21 @@ public Task<Role> GetNewUserRoleAsync(string roomId)
187187
private Task<RoomState?> WithConnection(string connectionId, Func<RoomState, User, RoomState?> updateRoom)
188188
{
189189
if (ConnectionsToRoom.TryGetValue(connectionId, out string? roomId) &&
190-
ConnectionsToUser.TryGetValue(connectionId, out User? user))
190+
ConnectionsToUserId.TryGetValue(connectionId, out Guid userId))
191191
{
192-
return WithExistingRoom(roomId, room => updateRoom(room, user));
192+
return WithExistingRoom(roomId, userId, (room, user) => updateRoom(room, user));
193193
}
194194
return Task.FromResult<RoomState?>(null);
195195
}
196196

197-
private Task<RoomState?> WithExistingRoom(string roomId, Func<RoomState, RoomState?> updateRoom)
197+
private Task<RoomState?> WithExistingRoom(string roomId, Guid userId, Func<RoomState, User, RoomState?> updateRoom)
198198
{
199199
return WithRoomLock(roomId, () =>
200200
{
201-
if (Rooms.TryGetValue(roomId, out RoomState? existingRoom))
201+
if (Rooms.TryGetValue(roomId, out RoomState? existingRoom) &&
202+
existingRoom.Users.SingleOrDefault(x => x.Id == userId) is { } user)
202203
{
203-
RoomState? updatedRoom = updateRoom(existingRoom);
204+
RoomState? updatedRoom = updateRoom(existingRoom, user);
204205
if (updatedRoom is not null)
205206
{
206207
if (Rooms.TryUpdate(roomId, updatedRoom, existingRoom))

PointerStar/Shared/RoomState.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
public record class RoomState(string RoomId, User[] Users)
44
{
55
public IReadOnlyList<User> TeamMembers
6-
=> Users.Where(u => u.Role == Role.TeamMember).ToList();
6+
=> [.. Users.Where(u => u.Role == Role.TeamMember)];
77

88
public IReadOnlyList<User> Facilitators
9-
=> Users.Where(u => u.Role == Role.Facilitator).ToList();
9+
=> [.. Users.Where(u => u.Role == Role.Facilitator)];
1010

1111
public IReadOnlyList<User> Observers
12-
=> Users.Where(u => u.Role == Role.Observer).ToList();
12+
=> [.. Users.Where(u => u.Role == Role.Observer)];
1313

1414
public bool VotesShown { get; init; }
1515
//We want the default to be true so new facilitators have this on by default
@@ -24,9 +24,6 @@ public IReadOnlyList<User> Observers
2424
"8",
2525
"13",
2626
"21",
27-
"34",
28-
"55",
29-
"89",
3027
"Abstain",
3128
"?"
3229
};

0 commit comments

Comments
 (0)