commit
d17a642d28
|
|
@ -5,6 +5,7 @@ public class AgentTaskFilter
|
|||
public Pagination Pager { get; set; } = new Pagination();
|
||||
public string? AgentId { get; set; }
|
||||
public bool? Enabled { get; set; }
|
||||
public string? Status { get; set; }
|
||||
|
||||
public static AgentTaskFilter Empty()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
public class TaskExecutionStatus
|
||||
/// <summary>
|
||||
/// Agent task status
|
||||
/// </summary>
|
||||
public class TaskStatus
|
||||
{
|
||||
public const string Scheduled = "scheduled";
|
||||
public const string New = "new";
|
||||
public const string Running = "running";
|
||||
public const string Success = "success";
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
using BotSharp.Abstraction.Tasks.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Tasks;
|
||||
|
||||
public interface ITaskFeeder
|
||||
{
|
||||
Task<List<AgentTask>> GetTasks();
|
||||
}
|
||||
|
|
@ -1,35 +1,27 @@
|
|||
namespace BotSharp.Abstraction.Tasks.Models;
|
||||
|
||||
public class AgentTask : AgentTaskMetaData
|
||||
public class AgentTask
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Content { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public string AgentId { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public Agent Agent { get; set; }
|
||||
|
||||
public AgentTask()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AgentTask(string id, string name, string? description = null)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Description = description;
|
||||
}
|
||||
}
|
||||
|
||||
public class AgentTaskMetaData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public string? DirectAgentId { get; set; }
|
||||
public string Content { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public string AgentId { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public Agent Agent { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Agent task status
|
||||
/// </summary>
|
||||
public string Status { get; set; } = TaskStatus.New;
|
||||
|
||||
public DateTime? LastExecutedDateTime { get; set; }
|
||||
public DateTime? NextExecutionDateTime { get; set; }
|
||||
|
||||
public DateTime CreatedDateTime { get; set; }
|
||||
public DateTime UpdatedDateTime { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
using BotSharp.Abstraction.Tasks;
|
||||
using BotSharp.Core.Crontab.Hooks;
|
||||
|
||||
namespace BotSharp.Core.Crontab;
|
||||
|
|
@ -33,6 +34,8 @@ public class CrontabPlugin : IBotSharpPlugin
|
|||
{
|
||||
services.AddScoped<IAgentUtilityHook, CrontabUtilityHook>();
|
||||
services.AddScoped<ICrontabService, CrontabService>();
|
||||
services.AddScoped<ITaskFeeder, CrontabService>();
|
||||
|
||||
services.AddHostedService<CrontabWatcher>();
|
||||
services.AddHostedService<CrontabEventSubscription>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,14 @@
|
|||
******************************************************************************/
|
||||
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Tasks;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Abstraction.Utilities;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace BotSharp.Core.Crontab.Services;
|
||||
|
||||
|
|
@ -24,7 +30,7 @@ namespace BotSharp.Core.Crontab.Services;
|
|||
/// The Crontab service schedules distributed events based on the execution times provided by users.
|
||||
/// In a scalable environment, distributed locks are used to ensure that each event is triggered only once.
|
||||
/// </summary>
|
||||
public class CrontabService : ICrontabService
|
||||
public class CrontabService : ICrontabService, ITaskFeeder
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private ILogger _logger;
|
||||
|
|
@ -52,6 +58,57 @@ public class CrontabService : ICrontabService
|
|||
return fixedCrantabItems;
|
||||
}
|
||||
|
||||
public async Task<List<AgentTask>> GetTasks()
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var tasks = new List<AgentTask>();
|
||||
var cronsources = _services.GetServices<ICrontabSource>();
|
||||
foreach (var source in cronsources)
|
||||
{
|
||||
var cron = source.GetCrontabItem();
|
||||
|
||||
// Get all agent subscribed to this cron
|
||||
|
||||
var agents = await agentService.GetAgents(new AgentFilter
|
||||
{
|
||||
Pager = new Pagination
|
||||
{
|
||||
Size = 1000
|
||||
}
|
||||
});
|
||||
|
||||
var preFilteredAgents = agents.Items.Where(x =>
|
||||
x.Rules.Exists(r => r.TriggerName == cron.Title)).ToList();
|
||||
|
||||
tasks.AddRange(preFilteredAgents.Select(x => new AgentTask
|
||||
{
|
||||
Id = Guid.Empty.ToString(),
|
||||
AgentId = x.Id,
|
||||
Agent = new BotSharp.Abstraction.Agents.Models.Agent
|
||||
{
|
||||
Name = x.Name,
|
||||
Description = x.Description
|
||||
},
|
||||
Name = FormatCrontabName(cron.Title, x.Name),
|
||||
Content = $"Trigger: {cron.Title}\r\nAgent: {x.Name}\r\nCron expression: {cron.Cron}",
|
||||
Status = TaskStatus.Scheduled,
|
||||
Enabled = !x.Disabled,
|
||||
Description = cron.Description,
|
||||
LastExecutedDateTime = cron.LastExecutionTime
|
||||
}));
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
private string FormatCrontabName(string trigger, string agent)
|
||||
{
|
||||
trigger = trigger.Replace("RuleTrigger", string.Empty);
|
||||
trigger = Regex.Replace(trigger, "(?<!^)([A-Z])", " $1");
|
||||
agent = agent.Replace("Operator", string.Empty);
|
||||
return $"{trigger}";
|
||||
}
|
||||
|
||||
public async Task ScheduledTimeArrived(CrontabItem item)
|
||||
{
|
||||
_logger.LogDebug($"ScheduledTimeArrived {item}");
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@ public partial class AgentService
|
|||
Name = parsedTask.Name,
|
||||
Description = parsedTask.Description,
|
||||
Enabled = parsedTask.Enabled,
|
||||
DirectAgentId = parsedTask.DirectAgentId,
|
||||
Content = parsedTask.Content,
|
||||
AgentId = agentId,
|
||||
CreatedDateTime = parsedTask.CreatedDateTime,
|
||||
|
|
|
|||
|
|
@ -119,12 +119,11 @@ public partial class FileRepository
|
|||
|
||||
var fileName = $"{Guid.NewGuid()}.liquid";
|
||||
var taskFile = Path.Combine(taskDir, fileName);
|
||||
var metaData = new AgentTaskMetaData
|
||||
var metaData = new AgentTask
|
||||
{
|
||||
Name = task.Name,
|
||||
Description = task.Description,
|
||||
Enabled = task.Enabled,
|
||||
DirectAgentId = task.DirectAgentId,
|
||||
CreatedDateTime = DateTime.UtcNow,
|
||||
UpdatedDateTime = DateTime.UtcNow
|
||||
};
|
||||
|
|
@ -154,12 +153,11 @@ public partial class FileRepository
|
|||
var parsedTask = ParseAgentTask(taskFile);
|
||||
if (parsedTask == null) return;
|
||||
|
||||
var metaData = new AgentTaskMetaData
|
||||
var metaData = new AgentTask
|
||||
{
|
||||
Name = parsedTask.Name,
|
||||
Description = parsedTask.Description,
|
||||
Enabled = parsedTask.Enabled,
|
||||
DirectAgentId = parsedTask.DirectAgentId,
|
||||
CreatedDateTime = parsedTask.CreatedDateTime,
|
||||
UpdatedDateTime = DateTime.UtcNow
|
||||
};
|
||||
|
|
@ -176,9 +174,6 @@ public partial class FileRepository
|
|||
case AgentTaskField.Enabled:
|
||||
metaData.Enabled = task.Enabled;
|
||||
break;
|
||||
case AgentTaskField.DirectAgentId:
|
||||
metaData.DirectAgentId = task.DirectAgentId;
|
||||
break;
|
||||
case AgentTaskField.Content:
|
||||
content = task.Content;
|
||||
break;
|
||||
|
|
@ -186,7 +181,6 @@ public partial class FileRepository
|
|||
metaData.Name = task.Name;
|
||||
metaData.Description = task.Description;
|
||||
metaData.Enabled = task.Enabled;
|
||||
metaData.DirectAgentId = task.DirectAgentId;
|
||||
content = task.Content;
|
||||
break;
|
||||
}
|
||||
|
|
@ -235,7 +229,7 @@ public partial class FileRepository
|
|||
return taskFile;
|
||||
}
|
||||
|
||||
private string BuildAgentTaskFileContent(AgentTaskMetaData metaData, string taskContent)
|
||||
private string BuildAgentTaskFileContent(AgentTask metaData, string taskContent)
|
||||
{
|
||||
return $"{AGENT_TASK_PREFIX}\n{JsonSerializer.Serialize(metaData, _options)}\n{AGENT_TASK_SUFFIX}\n\n{taskContent}";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Tasks;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
|
||||
|
|
@ -20,9 +18,23 @@ public class AgentTaskService : IAgentTaskService
|
|||
/// <returns></returns>
|
||||
public async Task<PagedItems<AgentTask>> GetTasks(AgentTaskFilter filter)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var pagedTasks = db.GetAgentTasks(filter);
|
||||
return await Task.FromResult(pagedTasks);
|
||||
if (filter.Status == TaskStatus.Scheduled)
|
||||
{
|
||||
var taskFeeders = _services.GetServices<ITaskFeeder>();
|
||||
var items = taskFeeders.SelectMany(x => x.GetTasks().Result);
|
||||
|
||||
return new PagedItems<AgentTask>
|
||||
{
|
||||
Items = items,
|
||||
Count = items.Count()
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var pagedTasks = db.GetAgentTasks(filter);
|
||||
return await Task.FromResult(pagedTasks);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(TargetFramework)</TargetFramework>
|
||||
|
|
@ -47,7 +47,6 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BotSharp.Core.Rules\BotSharp.Core.Rules.csproj" />
|
||||
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,11 @@ public class AgentTaskController : ControllerBase
|
|||
[HttpGet("/agent/tasks")]
|
||||
public async Task<PagedItems<AgentTaskViewModel>> GetAgentTasks([FromQuery] AgentTaskFilter filter)
|
||||
{
|
||||
filter.Status = TaskStatus.Scheduled;
|
||||
var tasks = await _agentTaskService.GetTasks(filter);
|
||||
return new PagedItems<AgentTaskViewModel>
|
||||
{
|
||||
Items = tasks.Items.Select(x => AgentTaskViewModel.From(x)),
|
||||
Items = tasks.Items.Select(AgentTaskViewModel.From),
|
||||
Count = tasks.Count
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
using BotSharp.Abstraction.Options;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Rules;
|
||||
using BotSharp.Core.Rules.Triggers;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ public class AgentTaskCreateModel
|
|||
public string? Description { get; set; }
|
||||
public string Content { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public string? DirectAgentId { get; set; }
|
||||
|
||||
public AgentTask ToAgentTask()
|
||||
{
|
||||
|
|
@ -17,8 +16,7 @@ public class AgentTaskCreateModel
|
|||
Name = Name,
|
||||
Description = Description,
|
||||
Content = Content,
|
||||
Enabled = Enabled,
|
||||
DirectAgentId = DirectAgentId
|
||||
Enabled = Enabled
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ public class AgentTaskUpdateModel
|
|||
public string? Description { get; set; }
|
||||
public string? Content { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public string? DirectAgentId { get; set; }
|
||||
|
||||
public AgentTask ToAgentTask()
|
||||
{
|
||||
|
|
@ -17,8 +16,7 @@ public class AgentTaskUpdateModel
|
|||
Name = Name,
|
||||
Description = Description,
|
||||
Content = Content,
|
||||
Enabled = Enabled,
|
||||
DirectAgentId = DirectAgentId
|
||||
Enabled = Enabled
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,21 +5,22 @@ namespace BotSharp.OpenAPI.ViewModels.Agents;
|
|||
|
||||
public class AgentTaskViewModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Id { get; set; } = null!;
|
||||
public string Name { get; set; } = null!;
|
||||
public string? Description { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string Content { get; set; } = null!;
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public string Status { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("created_datetime")]
|
||||
public DateTime CreatedDateTime { get; set; }
|
||||
[JsonPropertyName("updated_datetime")]
|
||||
public DateTime UpdatedDateTime { get; set; }
|
||||
[JsonPropertyName("agent_id")]
|
||||
public string AgentId { get; set; }
|
||||
public string AgentId { get; set; } = null!;
|
||||
[JsonPropertyName("agent_name")]
|
||||
public string AgentName { get; set; }
|
||||
[JsonPropertyName("direct_agent_id")]
|
||||
public string? DirectAgentId { get; set; }
|
||||
public string AgentName { get; set; } = null!;
|
||||
|
||||
public static AgentTaskViewModel From(AgentTask task)
|
||||
{
|
||||
|
|
@ -32,7 +33,7 @@ public class AgentTaskViewModel
|
|||
Enabled = task.Enabled,
|
||||
AgentId = task.AgentId,
|
||||
AgentName = task.Agent?.Name,
|
||||
DirectAgentId = task?.DirectAgentId,
|
||||
Status = task.Status,
|
||||
CreatedDateTime = task.CreatedDateTime,
|
||||
UpdatedDateTime = task.UpdatedDateTime
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ public partial class MongoRepository
|
|||
Description = x.Description,
|
||||
Enabled = x.Enabled,
|
||||
AgentId = x.AgentId,
|
||||
DirectAgentId = x.DirectAgentId,
|
||||
Content = x.Content,
|
||||
CreatedDateTime = x.CreatedTime,
|
||||
UpdatedDateTime = x.UpdatedTime,
|
||||
|
|
@ -73,7 +72,6 @@ public partial class MongoRepository
|
|||
Description = taskDoc.Description,
|
||||
Enabled = taskDoc.Enabled,
|
||||
AgentId = taskDoc.AgentId,
|
||||
DirectAgentId = taskDoc.DirectAgentId,
|
||||
Content = taskDoc.Content,
|
||||
CreatedDateTime = taskDoc.CreatedTime,
|
||||
UpdatedDateTime = taskDoc.UpdatedTime,
|
||||
|
|
@ -92,7 +90,6 @@ public partial class MongoRepository
|
|||
Description = task.Description,
|
||||
Enabled = task.Enabled,
|
||||
AgentId = task.AgentId,
|
||||
DirectAgentId = task.DirectAgentId,
|
||||
Content = task.Content,
|
||||
CreatedTime = DateTime.UtcNow,
|
||||
UpdatedTime = DateTime.UtcNow
|
||||
|
|
@ -112,7 +109,6 @@ public partial class MongoRepository
|
|||
Description = x.Description,
|
||||
Enabled = x.Enabled,
|
||||
AgentId = x.AgentId,
|
||||
DirectAgentId = x.DirectAgentId,
|
||||
Content = x.Content,
|
||||
CreatedTime = x.CreatedDateTime,
|
||||
UpdatedTime = x.UpdatedDateTime
|
||||
|
|
@ -143,15 +139,11 @@ public partial class MongoRepository
|
|||
case AgentTaskField.Content:
|
||||
taskDoc.Content = task.Content;
|
||||
break;
|
||||
case AgentTaskField.DirectAgentId:
|
||||
taskDoc.DirectAgentId = task.DirectAgentId;
|
||||
break;
|
||||
case AgentTaskField.All:
|
||||
taskDoc.Name = task.Name;
|
||||
taskDoc.Description = task.Description;
|
||||
taskDoc.Enabled = task.Enabled;
|
||||
taskDoc.Content = task.Content;
|
||||
taskDoc.DirectAgentId = task.DirectAgentId;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue