Импорт
This commit is contained in:
@@ -8,7 +8,7 @@ using Knot.Contracts.Auth.Infrastructure.Persistence;
|
||||
using Knot.Contracts.Conversations.Domain;
|
||||
using Knot.Contracts.Conversations.Infrastructure.Persistence;
|
||||
using Knot.Contracts.Messaging.Application.Abstractions;
|
||||
using Knot.Contracts.Storage.Abstractions;
|
||||
using Knot.Shared.Kernel.Storage;
|
||||
using Knot.Contracts.Stories.Infrastructure.Persistence;
|
||||
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||
using MediatR;
|
||||
@@ -51,7 +51,7 @@ internal sealed class CleanRunCommandHandler : ICommandHandler<CleanRunCommand,
|
||||
var orphanMessages = await _messageQueryService.GetOrphanedMessagesAsync(activeChatIds, cancellationToken);
|
||||
|
||||
var keptMessages = allMessages
|
||||
.Where(m => !orphanMessages.Any(om => om.Id == m.Id))
|
||||
.Where(m => !orphanMessages.Any(om => om.Id == m.Id) && !m.IsDeleted)
|
||||
.ToList();
|
||||
|
||||
var allMinioFiles = (await _fileStorage.ListFilesAsync()).ToList();
|
||||
|
||||
+35
-14
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -8,6 +8,7 @@ using Knot.Contracts.Auth.Infrastructure.Persistence;
|
||||
using Knot.Contracts.Conversations.Domain;
|
||||
using Knot.Contracts.Conversations.Infrastructure.Persistence;
|
||||
using Knot.Contracts.Messaging.Application.Abstractions;
|
||||
using Knot.Shared.Kernel.Storage;
|
||||
using Knot.Contracts.Stories.Infrastructure.Persistence;
|
||||
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||
using MediatR;
|
||||
@@ -23,17 +24,20 @@ internal sealed class CleanDryRunQueryHandler : IQueryHandler<CleanDryRunQuery,
|
||||
private readonly IAuthDbContext _authDbContext;
|
||||
private readonly IChatsDbContext _chatsDbContext;
|
||||
private readonly IStoryCollection _storyCollection;
|
||||
private readonly IFileStorageService _fileStorage;
|
||||
|
||||
public CleanDryRunQueryHandler(
|
||||
Knot.Contracts.Messaging.Application.Abstractions.IMessageQueryService messageService,
|
||||
IAuthDbContext authDbContext,
|
||||
IChatsDbContext chatsDbContext,
|
||||
IStoryCollection storyCollection)
|
||||
IStoryCollection storyCollection,
|
||||
IFileStorageService fileStorage)
|
||||
{
|
||||
_messageService = messageService;
|
||||
_authDbContext = authDbContext;
|
||||
_chatsDbContext = chatsDbContext;
|
||||
_storyCollection = storyCollection;
|
||||
_fileStorage = fileStorage;
|
||||
}
|
||||
|
||||
public async Task<Result<CleanDryRunResult>> Handle(CleanDryRunQuery request, CancellationToken ct)
|
||||
@@ -46,25 +50,42 @@ internal sealed class CleanDryRunQueryHandler : IQueryHandler<CleanDryRunQuery,
|
||||
var orphanedMediaCount = orphanedMessages.Count(m => m.MediaUrl != null);
|
||||
var orphanedMessageCount = orphanedMessages.Count;
|
||||
|
||||
var validIds = new HashSet<string>();
|
||||
foreach (var msg in orphanedMessages.Where(m => m.MediaUrl != null))
|
||||
{
|
||||
var parts = msg.MediaUrl.Split('/');
|
||||
var fileId = parts.LastOrDefault();
|
||||
if (!string.IsNullOrEmpty(fileId))
|
||||
{
|
||||
validIds.Add(fileId);
|
||||
}
|
||||
}
|
||||
|
||||
var allMessages = await _messageService.GetAllMessagesAsync(ct);
|
||||
var keptMessages = allMessages
|
||||
.Where(m => !orphanedMessages.Any(om => om.Id == m.Id) && !m.IsDeleted)
|
||||
.ToList();
|
||||
var allUsers = await _authDbContext.Users.ToListAsync(ct);
|
||||
var stories = await _storyCollection.GetAllAsync(ct);
|
||||
|
||||
var validUrls = new HashSet<string>();
|
||||
|
||||
var activeMessageUrls = keptMessages.Where(m => m.Media != null).SelectMany(m => m.Media!).Select(x => x.Url).Where(u => !string.IsNullOrEmpty(u));
|
||||
var activeChatUrls = _chatsDbContext.Chats.Select(c => c.Avatar).Where(u => !string.IsNullOrEmpty(u));
|
||||
var activeUserUrls = allUsers.Select(u => u.Avatar).Where(u => !string.IsNullOrEmpty(u));
|
||||
var activeStoryUrls = stories.Select(s => s.MediaUrl).Where(u => !string.IsNullOrEmpty(u));
|
||||
|
||||
foreach (var u in activeMessageUrls) validUrls.Add(u!);
|
||||
foreach (var u in activeChatUrls) validUrls.Add(u!);
|
||||
foreach (var u in activeUserUrls) validUrls.Add(u!);
|
||||
foreach (var u in activeStoryUrls) validUrls.Add(u!);
|
||||
|
||||
var validFileIds = validUrls
|
||||
.Where(u => u.Contains("/api/files/"))
|
||||
.Select(u => u.Split('/').Last())
|
||||
.ToHashSet();
|
||||
|
||||
var allMinioFiles = await _fileStorage.ListFilesAsync();
|
||||
long orphanedFileSize = allMinioFiles
|
||||
.Where(f => !validFileIds.Contains(f.FileId))
|
||||
.Sum(f => f.Size);
|
||||
|
||||
var expiredStoriesCount = stories.Count(s => s.ExpiresAt.HasValue && s.ExpiresAt.Value < DateTime.UtcNow);
|
||||
var expiredStoriesSize = stories.Where(s => s.ExpiresAt.HasValue && s.ExpiresAt.Value < DateTime.UtcNow).Sum(s => s.MediaUrl?.Length ?? 0);
|
||||
|
||||
return Result.Success(new CleanDryRunResult(
|
||||
orphanedMessageCount,
|
||||
orphanedMediaCount,
|
||||
0,
|
||||
orphanedFileSize,
|
||||
expiredStoriesCount,
|
||||
expiredStoriesSize
|
||||
));
|
||||
|
||||
@@ -131,6 +131,17 @@ public static class AdminEndpoints
|
||||
return Results.Ok(result.Value);
|
||||
});
|
||||
|
||||
group.MapPost("clean/run", async (ISender sender, CancellationToken ct) =>
|
||||
{
|
||||
var result = await sender.Send(new CleanRunCommand(), ct);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
Console.WriteLine($"[Admin] Cleanup Run Error: {result.Error.Description}");
|
||||
return Results.BadRequest(new { error = result.Error.Description });
|
||||
}
|
||||
return Results.Ok(result.Value);
|
||||
});
|
||||
|
||||
group.MapGet("timezones", () =>
|
||||
{
|
||||
// Получаем все системные часовые пояса и формируем удобный для фронтенда формат
|
||||
|
||||
Reference in New Issue
Block a user