fix: align backend APIs and upload flow

This commit is contained in:
2026-09-15 14:10:55 +08:00
parent 32177a7293
commit 53e6195938
149 changed files with 4791 additions and 435 deletions
@@ -1,5 +1,6 @@
using MessageService.Domain.Entities;
using MessageService.Domain.IReposities;
using MessageService.Domain.Models;
using Microsoft.EntityFrameworkCore;
namespace MessageService.Infrastructure.Reposities
@@ -18,31 +19,54 @@ namespace MessageService.Infrastructure.Reposities
db.Conversations.Add(conversation);
}
public async Task<IEnumerable<string>> FindAllStreamKeyAsync(Guid userId)
public async Task<IEnumerable<string>> FindAllStreamKeyAsync(Guid userId, CancellationToken cancellationToken = default)
{
return await db.Conversations.Where(x => x.UserId == userId)
.AsNoTracking()
.Select(s => s.StreamKey)
.ToListAsync();
.ToListAsync(cancellationToken);
}
public async Task<Conversation?> FindByIdAsync(Guid id)
public async Task<Conversation?> FindByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
return await db.Conversations.FirstOrDefaultAsync(x => x.Id == id);
return await db.Conversations.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
}
public async Task<IEnumerable<Conversation>> FindByStreamKeyAsync(string streamKey)
public async Task<IEnumerable<Conversation>> FindByStreamKeyAsync(string streamKey, CancellationToken cancellationToken = default)
{
return await db.Conversations.Where(x => x.StreamKey == streamKey).ToListAsync();
return await db.Conversations.Where(x => x.StreamKey == streamKey).ToListAsync(cancellationToken);
}
public async Task<IEnumerable<Conversation>> FindByTargetIdAsync(Guid targetId)
public async Task<IEnumerable<Conversation>> FindByTargetIdAsync(Guid targetId, CancellationToken cancellationToken = default)
{
return await db.Conversations.Where(x => x.TargetId == targetId).ToListAsync();
return await db.Conversations.Where(x => x.TargetId == targetId).ToListAsync(cancellationToken);
}
public async Task<IEnumerable<Conversation>> FindByUserIdAsync(Guid userId)
public async Task<IReadOnlyList<ConversationSummary>> ListByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
{
return await db.Conversations.Where(x => x.UserId == userId).ToListAsync();
return await db.Conversations
.AsNoTracking()
.Where(x => x.UserId == userId)
.OrderByDescending(x => x.LastMessageTime ?? x.CreationTime)
.Select(x => new ConversationSummary(
x.Id,
x.UserId,
x.TargetId,
x.TargetAvatar,
x.TargetName,
x.LastReadSequenceId,
x.UnreadCount,
x.ChatType,
x.LastMessage,
x.LastMessageTime ?? x.CreationTime))
.ToListAsync(cancellationToken);
}
public Task<Conversation?> FindActiveAsync(Guid userId, Guid targetId, Domain.Enums.ChatType chatType, CancellationToken cancellationToken = default)
{
return db.Conversations.FirstOrDefaultAsync(
x => x.UserId == userId && x.TargetId == targetId && x.ChatType == chatType,
cancellationToken);
}
}
}
@@ -18,38 +18,68 @@ namespace MessageService.Infrastructure.Reposities
db.Messages.Add(message);
}
public async Task<Message?> FindByIdAsync(Guid id)
public async Task<Message?> FindByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
return await db.Messages.FirstOrDefaultAsync(x => x.Id == id);
return await db.Messages.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
}
public async Task<(IEnumerable<Message> messages, bool hasMore)> GetAsync(string streamKey, long? cusor, int direction, int limit)
public async Task<(IEnumerable<Message> messages, bool hasMore)> GetAsync(string streamKey, long? cusor, int direction, int limit, CancellationToken cancellationToken = default)
{
var query = db.Messages.Where(x => x.StreamKey == streamKey);
List<Message> messages = [];
List<Message> fetched;
if (direction == 0) // Before: 找比锚点小的,按倒序排
{
if (cusor.HasValue)
query = query.Where(m => m.SequenceId < cusor.Value);
var list = await query
fetched = await query
.OrderByDescending(m => m.SequenceId) // 最新消息在最前
.Take(limit + 1)
.ToListAsync();
messages = [.. list.OrderBy(s => s.SequenceId)];
.ToListAsync(cancellationToken);
}
else
{
if (cusor is null)
return (messages, false);
return (Array.Empty<Message>(), false);
messages = await query.OrderBy(o => o.SequenceId)
fetched = await query
.Where(m => m.SequenceId > cusor.Value)
.OrderBy(o => o.SequenceId)
.Take(limit + 1)
.ToListAsync();
.ToListAsync(cancellationToken);
}
return (messages, messages.Count > limit);
var hasMore = fetched.Count > limit;
var messages = fetched.Take(limit).OrderBy(s => s.SequenceId).ToList();
return (messages, hasMore);
}
public async Task<(IEnumerable<Message> messages, bool hasMore)> SearchAsync(
string streamKey,
string keyword,
long? cursor,
int limit,
CancellationToken cancellationToken = default)
{
var query = db.Messages
.AsNoTracking()
.Where(message =>
message.StreamKey == streamKey &&
message.MsgType == Domain.Enums.MessageType.Text &&
message.State == Domain.Enums.MessageState.Sent &&
message.Content.Fallback.Contains(keyword));
if (cursor.HasValue)
{
query = query.Where(message => message.SequenceId < cursor.Value);
}
var fetched = await query
.OrderByDescending(message => message.SequenceId)
.Take(limit + 1)
.ToListAsync(cancellationToken);
return (fetched.Take(limit).ToList(), fetched.Count > limit);
}
}
}