Merge pull request #334 from iceljc/features/add-state-filter
Features/add state filter
This commit is contained in:
commit
ec4ec0816e
|
|
@ -16,4 +16,15 @@ public class ConversationFilter
|
|||
/// Agent task id
|
||||
/// </summary>
|
||||
public string? TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether each key in the list is in the conversation states and its value equals to target value if not empty
|
||||
/// </summary>
|
||||
public IEnumerable<KeyValue> States { get; set; } = new List<KeyValue>();
|
||||
}
|
||||
|
||||
public class KeyValue
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public string? Value { get; set; }
|
||||
}
|
||||
|
|
@ -103,11 +103,23 @@ namespace BotSharp.Core.Repository
|
|||
var convDir = FindConversationDirectory(conversationId);
|
||||
if (!string.IsNullOrEmpty(convDir))
|
||||
{
|
||||
var dialogDir = Path.Combine(convDir, DIALOG_FILE);
|
||||
if (File.Exists(dialogDir))
|
||||
var dialogFile = Path.Combine(convDir, DIALOG_FILE);
|
||||
if (File.Exists(dialogFile))
|
||||
{
|
||||
var texts = ParseDialogElements(dialogs);
|
||||
File.AppendAllLines(dialogDir, texts);
|
||||
File.AppendAllLines(dialogFile, texts);
|
||||
}
|
||||
|
||||
var convFile = Path.Combine(convDir, CONVERSATION_FILE);
|
||||
if (File.Exists(convFile))
|
||||
{
|
||||
var json = File.ReadAllText(convFile);
|
||||
var conv = JsonSerializer.Deserialize<Conversation>(json, _options);
|
||||
if (conv != null)
|
||||
{
|
||||
conv.UpdatedTime = DateTime.UtcNow;
|
||||
File.WriteAllText(convFile, JsonSerializer.Serialize(conv, _options));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -219,10 +231,10 @@ namespace BotSharp.Core.Repository
|
|||
var totalDirs = Directory.GetDirectories(dir);
|
||||
foreach (var d in totalDirs)
|
||||
{
|
||||
var path = Path.Combine(d, CONVERSATION_FILE);
|
||||
if (!File.Exists(path)) continue;
|
||||
var convFile = Path.Combine(d, CONVERSATION_FILE);
|
||||
if (!File.Exists(convFile)) continue;
|
||||
|
||||
var json = File.ReadAllText(path);
|
||||
var json = File.ReadAllText(convFile);
|
||||
var record = JsonSerializer.Deserialize<Conversation>(json, _options);
|
||||
if (record == null) continue;
|
||||
|
||||
|
|
@ -234,6 +246,30 @@ namespace BotSharp.Core.Repository
|
|||
if (filter?.UserId != null) matched = matched && record.UserId == filter.UserId;
|
||||
if (filter?.TaskId != null) matched = matched && record.TaskId == filter.TaskId;
|
||||
|
||||
// Check states
|
||||
if (filter != null && !filter.States.IsNullOrEmpty())
|
||||
{
|
||||
var stateFile = Path.Combine(d, STATE_FILE);
|
||||
var convStates = CollectConversationStates(stateFile);
|
||||
foreach (var pair in filter.States)
|
||||
{
|
||||
if (pair == null || string.IsNullOrWhiteSpace(pair.Key)) continue;
|
||||
|
||||
var foundState = convStates.FirstOrDefault(x => x.Key.IsEqualTo(pair.Key));
|
||||
if (foundState == null)
|
||||
{
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(pair.Value))
|
||||
{
|
||||
var curValue = foundState.Values.LastOrDefault()?.Data;
|
||||
matched = matched && pair.Value.IsEqualTo(curValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched) continue;
|
||||
records.Add(record);
|
||||
}
|
||||
|
|
@ -288,7 +324,7 @@ namespace BotSharp.Core.Repository
|
|||
|
||||
var json = File.ReadAllText(convFile);
|
||||
var conv = JsonSerializer.Deserialize<Conversation>(json, _options);
|
||||
if (conv == null || conv.CreatedTime > utcNow.AddHours(-bufferHours))
|
||||
if (conv == null || conv.UpdatedTime > utcNow.AddHours(-bufferHours))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ namespace BotSharp.OpenAPI.BackgroundServices
|
|||
var delay = Task.Delay(TimeSpan.FromHours(1));
|
||||
try
|
||||
{
|
||||
await CloseIdleConversationsAsync(TimeSpan.FromMinutes(10));
|
||||
await CleanIdleConversationsAsync();
|
||||
|
||||
await CloseIdleConversationsAsync(TimeSpan.FromMinutes(10));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -52,9 +51,7 @@ namespace BotSharp.OpenAPI.BackgroundServices
|
|||
.OrderBy(x => x.Priority)
|
||||
.ToList();
|
||||
var moment = DateTime.UtcNow.Add(-conversationIdleTimeout);
|
||||
var conversations =
|
||||
(await conversationService.GetLastConversations())
|
||||
.Where(c => c.CreatedTime <= moment);
|
||||
var conversations = (await conversationService.GetLastConversations()).Where(c => c.CreatedTime <= moment);
|
||||
foreach (var conversation in conversations)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ public class ConversationController : ControllerBase
|
|||
return ConversationViewModel.FromSession(conv);
|
||||
}
|
||||
|
||||
[HttpGet("/conversations")]
|
||||
public async Task<PagedItems<ConversationViewModel>> GetConversations([FromQuery] ConversationFilter filter)
|
||||
[HttpPost("/conversations")]
|
||||
public async Task<PagedItems<ConversationViewModel>> GetConversations([FromBody] ConversationFilter filter)
|
||||
{
|
||||
var service = _services.GetRequiredService<IConversationService>();
|
||||
var conversations = await service.GetConversations(filter);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using BotSharp.Abstraction.Repositories.Filters;
|
|||
using BotSharp.Abstraction.Repositories.Models;
|
||||
using BotSharp.Plugin.MongoStorage.Collections;
|
||||
using BotSharp.Plugin.MongoStorage.Models;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace BotSharp.Plugin.MongoStorage.Repository;
|
||||
|
||||
|
|
@ -224,6 +225,35 @@ public partial class MongoRepository
|
|||
if (!string.IsNullOrEmpty(filter.UserId)) filters.Add(builder.Eq(x => x.UserId, filter.UserId));
|
||||
if (!string.IsNullOrEmpty(filter.TaskId)) filters.Add(builder.Eq(x => x.TaskId, filter.TaskId));
|
||||
|
||||
// Check states
|
||||
if (!filter.States.IsNullOrEmpty())
|
||||
{
|
||||
var targetConvIds = new List<string>();
|
||||
|
||||
foreach (var pair in filter.States)
|
||||
{
|
||||
if (pair == null || string.IsNullOrWhiteSpace(pair.Key)) continue;
|
||||
|
||||
var query = _dc.ConversationStates.AsQueryable();
|
||||
var convIds = query.AsEnumerable().Where(x =>
|
||||
{
|
||||
var foundState = x.States.FirstOrDefault(s => s.Key.IsEqualTo(pair.Key));
|
||||
if (foundState == null) return false;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(pair.Value))
|
||||
{
|
||||
return pair.Value.IsEqualTo(foundState.Values.LastOrDefault()?.Data);
|
||||
}
|
||||
|
||||
return true;
|
||||
}).Select(x => x.ConversationId).ToList();
|
||||
|
||||
targetConvIds = targetConvIds.Concat(convIds).Distinct().ToList();
|
||||
}
|
||||
|
||||
filters.Add(builder.In(x => x.Id, targetConvIds));
|
||||
}
|
||||
|
||||
var filterDef = builder.And(filters);
|
||||
var sortDef = Builders<ConversationDocument>.Sort.Descending(x => x.CreatedTime);
|
||||
var pager = filter?.Pager ?? new Pagination();
|
||||
|
|
@ -258,7 +288,7 @@ public partial class MongoRepository
|
|||
{
|
||||
var records = new List<Conversation>();
|
||||
var conversations = _dc.Conversations.Aggregate()
|
||||
.Group(c => c.UserId, g => g.OrderByDescending(x => x.CreatedTime).First())
|
||||
.Group(c => c.UserId, g => g.First(x => x.CreatedTime == g.Select(y => y.CreatedTime).Max()))
|
||||
.ToList();
|
||||
return conversations.Select(c => new Conversation()
|
||||
{
|
||||
|
|
@ -276,7 +306,6 @@ public partial class MongoRepository
|
|||
public List<string> GetIdleConversations(int batchSize, int messageLimit, int bufferHours)
|
||||
{
|
||||
var page = 1;
|
||||
var pageLimit = 10;
|
||||
var batchLimit = 50;
|
||||
var utcNow = DateTime.UtcNow;
|
||||
var conversationIds = new List<string>();
|
||||
|
|
@ -286,11 +315,11 @@ public partial class MongoRepository
|
|||
batchSize = batchLimit;
|
||||
}
|
||||
|
||||
while (true && page < pageLimit)
|
||||
while (true)
|
||||
{
|
||||
var skip = (page - 1) * batchSize;
|
||||
var candidates = _dc.Conversations.AsQueryable()
|
||||
.Where(x => x.CreatedTime <= utcNow.AddHours(-bufferHours))
|
||||
.Where(x => x.UpdatedTime <= utcNow.AddHours(-bufferHours))
|
||||
.Skip(skip)
|
||||
.Take(batchSize)
|
||||
.Select(x => x.Id)
|
||||
|
|
|
|||
Loading…
Reference in a new issue