🧱 Relationship query supports isRelated
This commit is contained in:
@@ -53,7 +53,8 @@ public class AccountServiceGrpc(
|
|||||||
.FirstOrDefaultAsync(a => a.AutomatedId == automatedId);
|
.FirstOrDefaultAsync(a => a.AutomatedId == automatedId);
|
||||||
|
|
||||||
if (account == null)
|
if (account == null)
|
||||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, $"Account with automated ID {request.AutomatedId} not found"));
|
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound,
|
||||||
|
$"Account with automated ID {request.AutomatedId} not found"));
|
||||||
|
|
||||||
var perk = await subscriptions.GetPerkSubscriptionAsync(account.Id);
|
var perk = await subscriptions.GetPerkSubscriptionAsync(account.Id);
|
||||||
account.PerkSubscription = perk?.ToReference();
|
account.PerkSubscription = perk?.ToReference();
|
||||||
@@ -159,7 +160,8 @@ public class AccountServiceGrpc(
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<GetAccountBatchResponse> SearchAccount(SearchAccountRequest request, ServerCallContext context)
|
public override async Task<GetAccountBatchResponse> SearchAccount(SearchAccountRequest request,
|
||||||
|
ServerCallContext context)
|
||||||
{
|
{
|
||||||
var accounts = await _db.Accounts
|
var accounts = await _db.Accounts
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
@@ -232,21 +234,48 @@ public class AccountServiceGrpc(
|
|||||||
public override async Task<ListRelationshipSimpleResponse> ListFriends(
|
public override async Task<ListRelationshipSimpleResponse> ListFriends(
|
||||||
ListRelationshipSimpleRequest request, ServerCallContext context)
|
ListRelationshipSimpleRequest request, ServerCallContext context)
|
||||||
{
|
{
|
||||||
|
var resp = new ListRelationshipSimpleResponse();
|
||||||
|
switch (request.RelationIdentifierCase)
|
||||||
|
{
|
||||||
|
case ListRelationshipSimpleRequest.RelationIdentifierOneofCase.AccountId:
|
||||||
var accountId = Guid.Parse(request.AccountId);
|
var accountId = Guid.Parse(request.AccountId);
|
||||||
var relationship = await relationships.ListAccountFriends(accountId);
|
var relationship = await relationships.ListAccountFriends(accountId);
|
||||||
var resp = new ListRelationshipSimpleResponse();
|
|
||||||
resp.AccountsId.AddRange(relationship.Select(x => x.ToString()));
|
resp.AccountsId.AddRange(relationship.Select(x => x.ToString()));
|
||||||
return resp;
|
return resp;
|
||||||
|
case ListRelationshipSimpleRequest.RelationIdentifierOneofCase.RelatedId:
|
||||||
|
var relatedId = Guid.Parse(request.RelatedId);
|
||||||
|
var relatedRelationship = await relationships.ListAccountFriends(relatedId, true);
|
||||||
|
resp.AccountsId.AddRange(relatedRelationship.Select(x => x.ToString()));
|
||||||
|
return resp;
|
||||||
|
break;
|
||||||
|
case ListRelationshipSimpleRequest.RelationIdentifierOneofCase.None:
|
||||||
|
default:
|
||||||
|
throw new RpcException(new Status(StatusCode.InvalidArgument,
|
||||||
|
$"The relationship identifier must be provided."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<ListRelationshipSimpleResponse> ListBlocked(
|
public override async Task<ListRelationshipSimpleResponse> ListBlocked(
|
||||||
ListRelationshipSimpleRequest request, ServerCallContext context)
|
ListRelationshipSimpleRequest request, ServerCallContext context)
|
||||||
{
|
{
|
||||||
|
var resp = new ListRelationshipSimpleResponse();
|
||||||
|
switch (request.RelationIdentifierCase)
|
||||||
|
{
|
||||||
|
case ListRelationshipSimpleRequest.RelationIdentifierOneofCase.AccountId:
|
||||||
var accountId = Guid.Parse(request.AccountId);
|
var accountId = Guid.Parse(request.AccountId);
|
||||||
var relationship = await relationships.ListAccountBlocked(accountId);
|
var relationship = await relationships.ListAccountBlocked(accountId);
|
||||||
var resp = new ListRelationshipSimpleResponse();
|
|
||||||
resp.AccountsId.AddRange(relationship.Select(x => x.ToString()));
|
resp.AccountsId.AddRange(relationship.Select(x => x.ToString()));
|
||||||
return resp;
|
return resp;
|
||||||
|
case ListRelationshipSimpleRequest.RelationIdentifierOneofCase.RelatedId:
|
||||||
|
var relatedId = Guid.Parse(request.RelatedId);
|
||||||
|
var relatedRelationship = await relationships.ListAccountBlocked(relatedId, true);
|
||||||
|
resp.AccountsId.AddRange(relatedRelationship.Select(x => x.ToString()));
|
||||||
|
return resp;
|
||||||
|
case ListRelationshipSimpleRequest.RelationIdentifierOneofCase.None:
|
||||||
|
default:
|
||||||
|
throw new RpcException(new Status(StatusCode.InvalidArgument,
|
||||||
|
$"The relationship identifier must be provided."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<GetRelationshipResponse> GetRelationship(GetRelationshipRequest request,
|
public override async Task<GetRelationshipResponse> GetRelationship(GetRelationshipRequest request,
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ public class RelationshipService(
|
|||||||
return relationship;
|
return relationship;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SnAccountRelationship> CreateRelationship(SnAccount sender, SnAccount target, RelationshipStatus status)
|
public async Task<SnAccountRelationship> CreateRelationship(SnAccount sender, SnAccount target,
|
||||||
|
RelationshipStatus status)
|
||||||
{
|
{
|
||||||
if (status == RelationshipStatus.Pending)
|
if (status == RelationshipStatus.Pending)
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
@@ -169,12 +170,14 @@ public class RelationshipService(
|
|||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
await PurgeRelationshipCache(relationship.AccountId, relationship.RelatedId, RelationshipStatus.Friends, status);
|
await PurgeRelationshipCache(relationship.AccountId, relationship.RelatedId, RelationshipStatus.Friends,
|
||||||
|
status);
|
||||||
|
|
||||||
return relationshipBackward;
|
return relationshipBackward;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SnAccountRelationship> UpdateRelationship(Guid accountId, Guid relatedId, RelationshipStatus status)
|
public async Task<SnAccountRelationship> UpdateRelationship(Guid accountId, Guid relatedId,
|
||||||
|
RelationshipStatus status)
|
||||||
{
|
{
|
||||||
var relationship = await GetRelationship(accountId, relatedId);
|
var relationship = await GetRelationship(accountId, relatedId);
|
||||||
if (relationship is null) throw new ArgumentException("There is no relationship between you and the user.");
|
if (relationship is null) throw new ArgumentException("There is no relationship between you and the user.");
|
||||||
@@ -189,24 +192,26 @@ public class RelationshipService(
|
|||||||
return relationship;
|
return relationship;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Guid>> ListAccountFriends(SnAccount account)
|
public async Task<List<Guid>> ListAccountFriends(SnAccount account, bool isRelated = false)
|
||||||
{
|
{
|
||||||
return await ListAccountFriends(account.Id);
|
return await ListAccountFriends(account.Id, isRelated);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Guid>> ListAccountFriends(Guid accountId)
|
public async Task<List<Guid>> ListAccountFriends(Guid accountId, bool isRelated = false)
|
||||||
{
|
{
|
||||||
return await GetCachedRelationships(accountId, RelationshipStatus.Friends, UserFriendsCacheKeyPrefix);
|
return await GetCachedRelationships(accountId, RelationshipStatus.Friends, UserFriendsCacheKeyPrefix,
|
||||||
|
isRelated);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Guid>> ListAccountBlocked(SnAccount account)
|
public async Task<List<Guid>> ListAccountBlocked(SnAccount account, bool isRelated = false)
|
||||||
{
|
{
|
||||||
return await ListAccountBlocked(account.Id);
|
return await ListAccountBlocked(account.Id, isRelated);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Guid>> ListAccountBlocked(Guid accountId)
|
public async Task<List<Guid>> ListAccountBlocked(Guid accountId, bool isRelated = false)
|
||||||
{
|
{
|
||||||
return await GetCachedRelationships(accountId, RelationshipStatus.Blocked, UserBlockedCacheKeyPrefix);
|
return await GetCachedRelationships(accountId, RelationshipStatus.Blocked, UserBlockedCacheKeyPrefix,
|
||||||
|
isRelated);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> HasRelationshipWithStatus(Guid accountId, Guid relatedId,
|
public async Task<bool> HasRelationshipWithStatus(Guid accountId, Guid relatedId,
|
||||||
@@ -216,29 +221,26 @@ public class RelationshipService(
|
|||||||
return relationship is not null;
|
return relationship is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<Guid>> GetCachedRelationships(Guid accountId, RelationshipStatus status, string cachePrefix)
|
private async Task<List<Guid>> GetCachedRelationships(
|
||||||
|
Guid accountId,
|
||||||
|
RelationshipStatus status,
|
||||||
|
string cachePrefix,
|
||||||
|
bool isRelated = false
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (accountId == Guid.Empty)
|
if (accountId == Guid.Empty)
|
||||||
throw new ArgumentException("Account ID cannot be empty.");
|
throw new ArgumentException("Account ID cannot be empty.");
|
||||||
|
|
||||||
var cacheKey = $"{cachePrefix}{accountId}";
|
var cacheKey = $"{cachePrefix}{accountId}:{isRelated}";
|
||||||
var relationships = await cache.GetAsync<List<Guid>>(cacheKey);
|
var relationships = await cache.GetAsync<List<Guid>>(cacheKey);
|
||||||
|
|
||||||
if (relationships != null) return relationships;
|
if (relationships != null) return relationships;
|
||||||
var now = Instant.FromDateTimeUtc(DateTime.UtcNow);
|
var now = Instant.FromDateTimeUtc(DateTime.UtcNow);
|
||||||
var query = db.AccountRelationships
|
var query = db.AccountRelationships
|
||||||
.Where(r => r.RelatedId == accountId)
|
.Where(r => isRelated ? r.RelatedId == accountId : r.AccountId == accountId)
|
||||||
.Where(r => r.Status == status)
|
.Where(r => r.Status == status)
|
||||||
.Where(r => r.ExpiredAt == null || r.ExpiredAt > now)
|
.Where(r => r.ExpiredAt == null || r.ExpiredAt > now)
|
||||||
.Select(r => r.AccountId);
|
.Select(r => isRelated ? r.AccountId : r.RelatedId);
|
||||||
|
|
||||||
if (status == RelationshipStatus.Friends)
|
|
||||||
{
|
|
||||||
var usersBlockedByMe = db.AccountRelationships
|
|
||||||
.Where(r => r.AccountId == accountId && r.Status == RelationshipStatus.Blocked)
|
|
||||||
.Select(r => r.RelatedId);
|
|
||||||
query = query.Except(usersBlockedByMe);
|
|
||||||
}
|
|
||||||
|
|
||||||
relationships = await query.ToListAsync();
|
relationships = await query.ToListAsync();
|
||||||
|
|
||||||
|
|||||||
@@ -290,8 +290,6 @@ service AccountService {
|
|||||||
rpc ListConnections(ListConnectionsRequest) returns (ListConnectionsResponse) {}
|
rpc ListConnections(ListConnectionsRequest) returns (ListConnectionsResponse) {}
|
||||||
|
|
||||||
// Relationship Operations
|
// Relationship Operations
|
||||||
rpc ListRelationships(ListRelationshipsRequest) returns (ListRelationshipsResponse) {}
|
|
||||||
|
|
||||||
rpc GetRelationship(GetRelationshipRequest) returns (GetRelationshipResponse) {}
|
rpc GetRelationship(GetRelationshipRequest) returns (GetRelationshipResponse) {}
|
||||||
rpc HasRelationship(GetRelationshipRequest) returns (google.protobuf.BoolValue) {}
|
rpc HasRelationship(GetRelationshipRequest) returns (google.protobuf.BoolValue) {}
|
||||||
rpc ListFriends(ListRelationshipSimpleRequest) returns (ListRelationshipSimpleResponse) {}
|
rpc ListFriends(ListRelationshipSimpleRequest) returns (ListRelationshipSimpleResponse) {}
|
||||||
@@ -489,7 +487,10 @@ message GetRelationshipResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ListRelationshipSimpleRequest {
|
message ListRelationshipSimpleRequest {
|
||||||
|
oneof relation_identifier {
|
||||||
string account_id = 1;
|
string account_id = 1;
|
||||||
|
string related_id = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListRelationshipSimpleResponse {
|
message ListRelationshipSimpleResponse {
|
||||||
|
|||||||
Reference in New Issue
Block a user