🐛 Fix some issues in moving realm service

This commit is contained in:
2025-10-22 21:56:50 +08:00
parent d6c37784e1
commit ff03584518
6 changed files with 120 additions and 12 deletions

View File

@@ -35,6 +35,15 @@ public class RealmServiceGrpc(
: realm.ToProtoValue();
}
public override async Task<GetRealmBatchResponse> GetRealmBatch(GetRealmBatchRequest request, ServerCallContext context)
{
var ids = request.Ids.Select(Guid.Parse).ToList();
var realms = await db.Realms.Where(r => ids.Contains(r.Id)).ToListAsync();
var response = new GetRealmBatchResponse();
response.Realms.AddRange(realms.Select(r => r.ToProtoValue()));
return response;
}
public override async Task<GetUserRealmsResponse> GetUserRealms(GetUserRealmsRequest request,
ServerCallContext context)
{
@@ -48,6 +57,7 @@ public class RealmServiceGrpc(
.Include(m => m.Realm)
.Where(m => m.AccountId == accountId)
.Where(m => m.JoinedAt != null && m.LeaveAt == null)
.Where(m => m.Realm != null)
.Select(m => m.Realm!.Id)
.ToListAsync();
@@ -57,6 +67,14 @@ public class RealmServiceGrpc(
return new GetUserRealmsResponse { RealmIds = { realms.Select(g => g.ToString()) } };
}
public override async Task<GetPublicRealmsResponse> GetPublicRealms(Empty request, ServerCallContext context)
{
var realms = await db.Realms.Where(r => r.IsPublic).ToListAsync();
var response = new GetPublicRealmsResponse();
response.Realms.AddRange(realms.Select(r => r.ToProtoValue()));
return response;
}
public override async Task<Empty> SendInviteNotify(SendInviteNotifyRequest request, ServerCallContext context)
{
var member = request.Member;

View File

@@ -32,8 +32,12 @@ message RealmMember {
service RealmService {
// Get realm by id or slug
rpc GetRealm(GetRealmRequest) returns (Realm) {}
// Get realm batch by ids
rpc GetRealmBatch(GetRealmBatchRequest) returns (GetRealmBatchResponse) {}
// Get realms for a user
rpc GetUserRealms(GetUserRealmsRequest) returns (GetUserRealmsResponse) {}
// Get public realms
rpc GetPublicRealms(google.protobuf.Empty) returns (GetPublicRealmsResponse) {}
// Send invitation notification
rpc SendInviteNotify(SendInviteNotifyRequest) returns (google.protobuf.Empty) {}
// Check if member has required role
@@ -57,10 +61,22 @@ message GetUserRealmsRequest {
string account_id = 1;
}
message GetRealmBatchRequest {
repeated string ids = 1;
}
message GetRealmBatchResponse {
repeated Realm realms = 1;
}
message GetUserRealmsResponse {
repeated string realm_ids = 1;
}
message GetPublicRealmsResponse {
repeated Realm realms = 1;
}
message SendInviteNotifyRequest {
RealmMember member = 1;
}

View File

@@ -1,5 +1,6 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Google.Protobuf.WellKnownTypes;
namespace DysonNetwork.Shared.Registry;
@@ -26,6 +27,20 @@ public class RemoteRealmService(RealmService.RealmServiceClient realms)
return response.RealmIds.Select(Guid.Parse).ToList();
}
public async Task<List<SnRealm>> GetPublicRealms()
{
var response = await realms.GetPublicRealmsAsync(new Empty());
return response.Realms.Select(SnRealm.FromProtoValue).ToList();
}
public async Task<List<SnRealm>> GetRealmBatch(List<string> ids)
{
var request = new GetRealmBatchRequest();
request.Ids.AddRange(ids);
var response = await realms.GetRealmBatchAsync(request);
return response.Realms.Select(SnRealm.FromProtoValue).ToList();
}
public async Task SendInviteNotify(SnRealmMember member)
{
var protoMember = member.ToProtoValue();

View File

@@ -40,19 +40,23 @@ public class ActivityService(
debugInclude ??= new HashSet<string>();
// Get and process posts
var publicRealms = await rs.GetPublicRealms();
var publicRealmIds = publicRealms.Select(r => r.Id).ToList();
var postsQuery = db.Posts
.Include(e => e.RepliedPost)
.Include(e => e.ForwardedPost)
.Include(e => e.Categories)
.Include(e => e.Tags)
.Include(e => e.Realm)
.Where(e => e.RepliedPostId == null)
.Where(p => cursor == null || p.PublishedAt < cursor)
.Where(p => p.RealmId == null || publicRealmIds.Contains(p.RealmId.Value))
.OrderByDescending(p => p.PublishedAt)
.FilterWithVisibility(null, [], [], isListing: true)
.Take(take * 5);
var posts = await GetAndProcessPosts(postsQuery);
await LoadPostsRealmsAsync(posts, rs);
posts = RankPosts(posts, take);
var interleaved = new List<SnActivity>();
@@ -122,6 +126,9 @@ public class ActivityService(
userPublishers,
trackViews: true);
if (currentUser != null)
await LoadPostsRealmsAsync(posts, rs);
posts = RankPosts(posts, take);
var interleaved = new List<SnActivity>();
@@ -219,15 +226,19 @@ public class ActivityService(
private async Task<SnActivity?> GetShuffledPostsActivity(int count = 5)
{
var publicRealms = await rs.GetPublicRealms();
var publicRealmIds = publicRealms.Select(r => r.Id).ToList();
var postsQuery = db.Posts
.Include(p => p.Categories)
.Include(p => p.Tags)
.Include(p => p.Realm)
.Where(p => p.RepliedPostId == null)
.Where(p => p.RealmId == null || publicRealmIds.Contains(p.RealmId.Value))
.OrderBy(_ => EF.Functions.Random())
.Take(count);
var posts = await GetAndProcessPosts(postsQuery, trackViews: false);
await LoadPostsRealmsAsync(posts, rs);
return posts.Count == 0
? null
@@ -306,7 +317,6 @@ public class ActivityService(
.Include(e => e.ForwardedPost)
.Include(e => e.Categories)
.Include(e => e.Tags)
.Include(e => e.Realm)
.Where(e => e.RepliedPostId == null)
.Where(p => cursor == null || p.PublishedAt < cursor)
.OrderByDescending(p => p.PublishedAt)
@@ -315,10 +325,14 @@ public class ActivityService(
if (filteredPublishersId != null && filteredPublishersId.Count != 0)
query = query.Where(p => filteredPublishersId.Contains(p.PublisherId));
if (userRealms == null)
query = query.Where(p => p.Realm == null || p.Realm.IsPublic);
{
// For anonymous users, only show public realm posts or posts without realm
// Get public realm ids in the caller and pass them
query = query.Where(p => p.RealmId == null); // Modify in caller
}
else
query = query.Where(p =>
p.Realm == null || p.Realm.IsPublic || p.RealmId == null || userRealms.Contains(p.RealmId.Value));
p.RealmId == null || userRealms.Contains(p.RealmId.Value));
return query;
}
@@ -339,6 +353,23 @@ public class ActivityService(
};
}
private static async Task LoadPostsRealmsAsync(List<SnPost> posts, RemoteRealmService rs)
{
var postRealmIds = posts.Where(p => p.RealmId != null).Select(p => p.RealmId.Value).Distinct().ToList();
if (!postRealmIds.Any()) return;
var realms = await rs.GetRealmBatch(postRealmIds.Select(id => id.ToString()).ToList());
var realmDict = realms.ToDictionary(r => r.Id, r => r);
foreach (var post in posts.Where(p => p.RealmId != null))
{
if (post.RealmId != null && realmDict.TryGetValue(post.RealmId.Value, out var realm))
{
post.Realm = realm;
}
}
}
private static double CalculatePopularity(List<SnPost> posts)
{
var score = posts.Sum(p => p.Upvotes - p.Downvotes);

View File

@@ -35,9 +35,12 @@ public class ChatRoomController(
{
var chatRoom = await db.ChatRooms
.Where(c => c.Id == id)
.Include(e => e.Realm)
.FirstOrDefaultAsync();
if (chatRoom is null) return NotFound();
if (chatRoom.RealmId != null)
chatRoom.Realm = await rs.GetRealm(chatRoom.RealmId.Value.ToString());
if (chatRoom.Type != ChatRoomType.DirectMessage) return Ok(chatRoom);
if (HttpContext.Items["CurrentUser"] is Account currentUser)

View File

@@ -105,7 +105,10 @@ public class PostController(
var accountId = currentUser is null ? Guid.Empty : Guid.Parse(currentUser.Id);
var userPublishers = currentUser is null ? [] : await pub.GetUserPublishers(accountId);
var userRealms = currentUser is null ? [] : await rs.GetUserRealms(accountId);
var userRealms = currentUser is null ? new List<Guid>() : await rs.GetUserRealms(accountId);
var publicRealms = await rs.GetPublicRealms();
var publicRealmIds = publicRealms.Select(r => r.Id).ToList();
var visibleRealmIds = userRealms.Concat(publicRealmIds).Distinct().ToList();
var publisher = pubName == null ? null : await db.Publishers.FirstOrDefaultAsync(p => p.Name == pubName);
var realm = realmName == null ? null : (realmName != null ? await rs.GetRealmBySlug(realmName) : null);
@@ -115,7 +118,6 @@ public class PostController(
.Include(e => e.Tags)
.Include(e => e.RepliedPost)
.Include(e => e.ForwardedPost)
.Include(e => e.Realm)
.AsQueryable();
if (publisher != null)
query = query.Where(p => p.PublisherId == publisher.Id);
@@ -131,8 +133,7 @@ public class PostController(
query = query.Where(e => e.Attachments.Count > 0);
if (realm == null)
query = query.Where(p =>
p.RealmId == null || p.Realm == null || userRealms.Contains(p.RealmId.Value) || p.Realm.IsPublic);
query = query.Where(p => p.RealmId == null || visibleRealmIds.Contains(p.RealmId.Value));
switch (pinned)
{
@@ -185,11 +186,31 @@ public class PostController(
.ToListAsync();
posts = await ps.LoadPostInfo(posts, currentUser, true);
// Load realm data for posts that have realm
await LoadPostsRealmsAsync(posts, rs);
Response.Headers["X-Total"] = totalCount.ToString();
return Ok(posts);
}
private static async Task LoadPostsRealmsAsync(List<SnPost> posts, RemoteRealmService rs)
{
var postRealmIds = posts.Where(p => p.RealmId != null).Select(p => p.RealmId.Value).Distinct().ToList();
if (!postRealmIds.Any()) return;
var realms = await rs.GetRealmBatch(postRealmIds.Select(id => id.ToString()).ToList());
var realmDict = realms.GroupBy(r => r.Id).ToDictionary(g => g.Key, g => g.FirstOrDefault());
foreach (var post in posts.Where(p => p.RealmId != null))
{
if (post.RealmId != null && realmDict.TryGetValue(post.RealmId.Value, out var realm))
{
post.Realm = realm;
}
}
}
[HttpGet("{publisherName}/{slug}")]
public async Task<ActionResult<SnPost>> GetPost(string publisherName, string slug)
{
@@ -208,7 +229,6 @@ public class PostController(
var post = await db.Posts
.Include(e => e.Publisher)
.Where(e => e.Slug == slug && e.Publisher.Name == publisherName)
.Include(e => e.Realm)
.Include(e => e.Tags)
.Include(e => e.Categories)
.Include(e => e.RepliedPost)
@@ -217,6 +237,8 @@ public class PostController(
.FirstOrDefaultAsync();
if (post is null) return NotFound();
post = await ps.LoadPostInfo(post, currentUser);
if (post.RealmId != null)
post.Realm = await rs.GetRealm(post.RealmId.Value.ToString());
return Ok(post);
}
@@ -239,7 +261,6 @@ public class PostController(
var post = await db.Posts
.Where(e => e.Id == id)
.Include(e => e.Publisher)
.Include(e => e.Realm)
.Include(e => e.Tags)
.Include(e => e.Categories)
.Include(e => e.RepliedPost)
@@ -248,6 +269,10 @@ public class PostController(
.FirstOrDefaultAsync();
if (post is null) return NotFound();
post = await ps.LoadPostInfo(post, currentUser);
if (post.RealmId != null)
{
post.Realm = await rs.GetRealm(post.RealmId.Value.ToString());
}
return Ok(post);
}