add background service to clean idle conversations
This commit is contained in:
parent
2ce526dd2e
commit
eb9a2bb25e
|
|
@ -13,7 +13,8 @@ public interface IConversationService
|
|||
Task<PagedItems<Conversation>> GetConversations(ConversationFilter filter);
|
||||
Task<Conversation> UpdateConversationTitle(string id, string title);
|
||||
Task<List<Conversation>> GetLastConversations();
|
||||
Task<bool> DeleteConversation(string id);
|
||||
Task<List<string>> GetIdleConversations(int batchSize, int messageLimit);
|
||||
Task<bool> DeleteConversations(IEnumerable<string> ids);
|
||||
Task<bool> TruncateConversation(string conversationId, string messageId);
|
||||
Task<List<ContentLogOutputModel>> GetConversationContentLogs(string conversationId);
|
||||
Task<List<ConversationStateLogModel>> GetConversationStateLogs(string conversationId);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public interface IBotSharpRepository
|
|||
|
||||
#region Conversation
|
||||
void CreateNewConversation(Conversation conversation);
|
||||
bool DeleteConversation(string conversationId);
|
||||
bool DeleteConversations(IEnumerable<string> conversationIds);
|
||||
List<DialogElement> GetConversationDialogs(string conversationId);
|
||||
void UpdateConversationDialogElements(string conversationId, List<DialogContentUpdateModel> updateElements);
|
||||
void AppendConversationDialogs(string conversationId, List<DialogElement> dialogs);
|
||||
|
|
@ -59,6 +59,7 @@ public interface IBotSharpRepository
|
|||
PagedItems<Conversation> GetConversations(ConversationFilter filter);
|
||||
void UpdateConversationTitle(string conversationId, string title);
|
||||
List<Conversation> GetLastConversations();
|
||||
List<string> GetIdleConversations(int batchSize, int messageLimit);
|
||||
bool TruncateConversation(string conversationId, string messageId, bool cleanLog = false);
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ public partial class ConversationService : IConversationService
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteConversation(string id)
|
||||
public async Task<bool> DeleteConversations(IEnumerable<string> ids)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var isDeleted = db.DeleteConversation(id);
|
||||
var isDeleted = db.DeleteConversations(ids);
|
||||
return await Task.FromResult(isDeleted);
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +63,12 @@ public partial class ConversationService : IConversationService
|
|||
return db.GetLastConversations();
|
||||
}
|
||||
|
||||
public async Task<List<string>> GetIdleConversations(int batchSize, int messageLimit)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
return db.GetIdleConversations(batchSize, messageLimit);
|
||||
}
|
||||
|
||||
public async Task<Conversation> NewConversation(Conversation sess)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool DeleteConversation(string conversationId)
|
||||
public bool DeleteConversations(IEnumerable<string> conversationIds)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -184,6 +184,11 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<string> GetIdleConversations(int batchSize, int messageLimit)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<DialogElement> GetConversationDialogs(string conversationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -44,14 +44,17 @@ namespace BotSharp.Core.Repository
|
|||
}
|
||||
}
|
||||
|
||||
public bool DeleteConversation(string conversationId)
|
||||
public bool DeleteConversations(IEnumerable<string> conversationIds)
|
||||
{
|
||||
if (string.IsNullOrEmpty(conversationId)) return false;
|
||||
if (conversationIds.IsNullOrEmpty()) return false;
|
||||
|
||||
foreach (var conversationId in conversationIds)
|
||||
{
|
||||
var convDir = FindConversationDirectory(conversationId);
|
||||
if (string.IsNullOrEmpty(convDir)) return false;
|
||||
if (string.IsNullOrEmpty(convDir)) continue;
|
||||
|
||||
Directory.Delete(convDir, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -263,6 +266,29 @@ namespace BotSharp.Core.Repository
|
|||
.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetIdleConversations(int batchSize, int messageLimit)
|
||||
{
|
||||
var ids = new List<string>();
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir);
|
||||
var count = 0;
|
||||
|
||||
foreach (var d in Directory.GetDirectories(dir))
|
||||
{
|
||||
var conversationId = d.Split(Path.DirectorySeparatorChar).Last(); ;
|
||||
var dialogs = GetConversationDialogs(conversationId);
|
||||
if (dialogs.Count <= messageLimit)
|
||||
{
|
||||
ids.Add(conversationId);
|
||||
count++;
|
||||
if (count >= batchSize)
|
||||
{
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
|
||||
public bool TruncateConversation(string conversationId, string messageId, bool cleanLog = false)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,10 +23,12 @@ namespace BotSharp.OpenAPI.BackgroundServices
|
|||
while (true)
|
||||
{
|
||||
stoppingToken.ThrowIfCancellationRequested();
|
||||
var delay = Task.Delay(TimeSpan.FromMinutes(1));
|
||||
var delay = Task.Delay(TimeSpan.FromSeconds(10));
|
||||
try
|
||||
{
|
||||
await CloseIdleConversationsAsync(TimeSpan.FromMinutes(10));
|
||||
//await CloseIdleConversationsAsync(TimeSpan.FromMinutes(10));
|
||||
await CleanIdleConversationsAsync();
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -76,5 +78,17 @@ namespace BotSharp.OpenAPI.BackgroundServices
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CleanIdleConversationsAsync(int batchSize = 50, int messageLimit = 2)
|
||||
{
|
||||
using var scope = _services.CreateScope();
|
||||
var conversationService = scope.ServiceProvider.GetRequiredService<IConversationService>();
|
||||
var conversationIds = await conversationService.GetIdleConversations(batchSize, messageLimit);
|
||||
|
||||
if (!conversationIds.IsNullOrEmpty())
|
||||
{
|
||||
await conversationService.DeleteConversations(conversationIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||
using Microsoft.Net.Http.Headers;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.IdentityModel.JsonWebTokens;
|
||||
using BotSharp.OpenAPI.BackgroundServices;
|
||||
|
||||
namespace BotSharp.OpenAPI;
|
||||
|
||||
|
|
@ -29,6 +30,7 @@ public static class BotSharpOpenApiExtensions
|
|||
bool enableValidation)
|
||||
{
|
||||
services.AddScoped<IUserIdentity, UserIdentity>();
|
||||
services.AddHostedService<ConversationTimeoutService>();
|
||||
|
||||
// Add bearer authentication
|
||||
var schema = "MIXED_SCHEME";
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ public class ConversationController : ControllerBase
|
|||
public async Task<bool> DeleteConversation([FromRoute] string conversationId)
|
||||
{
|
||||
var conversationService = _services.GetRequiredService<IConversationService>();
|
||||
var response = await conversationService.DeleteConversation(conversationId);
|
||||
var response = await conversationService.DeleteConversations(new List<string> { conversationId });
|
||||
return response;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,17 +55,17 @@ public partial class MongoRepository
|
|||
_dc.ConversationStates.InsertOne(stateDoc);
|
||||
}
|
||||
|
||||
public bool DeleteConversation(string conversationId)
|
||||
public bool DeleteConversations(IEnumerable<string> conversationIds)
|
||||
{
|
||||
if (string.IsNullOrEmpty(conversationId)) return false;
|
||||
if (conversationIds.IsNullOrEmpty()) return false;
|
||||
|
||||
var filterConv = Builders<ConversationDocument>.Filter.Eq(x => x.Id, conversationId);
|
||||
var filterDialog = Builders<ConversationDialogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterSates = Builders<ConversationStateDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterExeLog = Builders<ExecutionLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterPromptLog = Builders<LlmCompletionLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterContentLog = Builders<ConversationContentLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterStateLog = Builders<ConversationStateLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterConv = Builders<ConversationDocument>.Filter.In(x => x.Id, conversationIds);
|
||||
var filterDialog = Builders<ConversationDialogDocument>.Filter.In(x => x.ConversationId, conversationIds);
|
||||
var filterSates = Builders<ConversationStateDocument>.Filter.In(x => x.ConversationId, conversationIds);
|
||||
var filterExeLog = Builders<ExecutionLogDocument>.Filter.In(x => x.ConversationId, conversationIds);
|
||||
var filterPromptLog = Builders<LlmCompletionLogDocument>.Filter.In(x => x.ConversationId, conversationIds);
|
||||
var filterContentLog = Builders<ConversationContentLogDocument>.Filter.In(x => x.ConversationId, conversationIds);
|
||||
var filterStateLog = Builders<ConversationStateLogDocument>.Filter.In(x => x.ConversationId, conversationIds);
|
||||
|
||||
var exeLogDeleted = _dc.ExectionLogs.DeleteMany(filterExeLog);
|
||||
var promptLogDeleted = _dc.LlmCompletionLogs.DeleteMany(filterPromptLog);
|
||||
|
|
@ -274,6 +274,15 @@ public partial class MongoRepository
|
|||
}).ToList();
|
||||
}
|
||||
|
||||
public List<string> GetIdleConversations(int batchSize, int messageLimit)
|
||||
{
|
||||
return _dc.ConversationDialogs.AsQueryable()
|
||||
.Where(x => x.Dialogs != null && x.Dialogs.Count <= messageLimit)
|
||||
.Take(batchSize)
|
||||
.Select(x => x.ConversationId)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public bool TruncateConversation(string conversationId, string messageId, bool cleanLog = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(conversationId) || string.IsNullOrEmpty(messageId)) return false;
|
||||
|
|
|
|||
Loading…
Reference in a new issue