ICrontabSource
This commit is contained in:
parent
3d1a4fc2ef
commit
bda1351a6c
|
|
@ -1,6 +0,0 @@
|
|||
namespace BotSharp.Abstraction.Agents;
|
||||
|
||||
public interface IAgentRuleHook
|
||||
{
|
||||
void AddRules(List<AgentRule> rules);
|
||||
}
|
||||
|
|
@ -5,8 +5,9 @@ public class ConversationChannel
|
|||
public const string WebChat = "webchat";
|
||||
public const string OpenAPI = "openapi";
|
||||
public const string Phone = "phone";
|
||||
public const string SMS = "sms";
|
||||
public const string Messenger = "messenger";
|
||||
public const string Email = "email";
|
||||
public const string Cron = "cron";
|
||||
public const string Crontab = "crontab";
|
||||
public const string Database = "database";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ public class CrontabItem : ScheduleTaskArgs
|
|||
[JsonPropertyName("expire_seconds")]
|
||||
public int ExpireSeconds { get; set; } = 60;
|
||||
|
||||
[JsonPropertyName("last_execution_time")]
|
||||
public DateTime? LastExecutionTime { get; set; }
|
||||
|
||||
[JsonPropertyName("created_time")]
|
||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,5 +2,12 @@ namespace BotSharp.Core.Crontab.Abstraction;
|
|||
|
||||
public interface ICrontabHook
|
||||
{
|
||||
Task OnCronTriggered(CrontabItem item);
|
||||
Task OnCronTriggered(CrontabItem item)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
Task OnTaskExecuting(CrontabItem item)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
Task OnTaskExecuted(CrontabItem item)
|
||||
=> Task.CompletedTask;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
namespace BotSharp.Core.Crontab.Abstraction;
|
||||
|
||||
/// <summary>
|
||||
/// Provide a cron source for the crontab service.
|
||||
/// </summary>
|
||||
public interface ICrontabSource
|
||||
{
|
||||
CrontabItem GetCrontabItem();
|
||||
}
|
||||
|
|
@ -39,7 +39,17 @@ public class CrontabService : ICrontabService
|
|||
{
|
||||
var repo = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var crontable = repo.GetCrontabItems(CrontabItemFilter.Empty());
|
||||
return crontable.Items.ToList();
|
||||
|
||||
// Add fixed crontab items from cronsources
|
||||
var fixedCrantabItems = crontable.Items.ToList();
|
||||
var cronsources = _services.GetServices<ICrontabSource>();
|
||||
foreach (var source in cronsources)
|
||||
{
|
||||
var item = source.GetCrontabItem();
|
||||
fixedCrantabItems.Add(source.GetCrontabItem());
|
||||
}
|
||||
|
||||
return fixedCrantabItems;
|
||||
}
|
||||
|
||||
public async Task ScheduledTimeArrived(CrontabItem item)
|
||||
|
|
@ -47,8 +57,10 @@ public class CrontabService : ICrontabService
|
|||
_logger.LogDebug($"ScheduledTimeArrived {item}");
|
||||
|
||||
await HookEmitter.Emit<ICrontabHook>(_services, async hook =>
|
||||
await hook.OnCronTriggered(item)
|
||||
);
|
||||
await Task.Delay(1000 * 10);
|
||||
{
|
||||
await hook.OnTaskExecuting(item);
|
||||
await hook.OnCronTriggered(item);
|
||||
await hook.OnTaskExecuted(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ public class CrontabWatcher : BackgroundService
|
|||
{
|
||||
var locker = scope.ServiceProvider.GetRequiredService<IDistributedLocker>();
|
||||
|
||||
/*while (!stoppingToken.IsCancellationRequested)
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
var delay = Task.Delay(1000, stoppingToken);
|
||||
var delay = Task.Delay(1000 * 10, stoppingToken);
|
||||
|
||||
await locker.LockAsync("CrontabWatcher", async () =>
|
||||
{
|
||||
|
|
@ -34,7 +34,7 @@ public class CrontabWatcher : BackgroundService
|
|||
});
|
||||
|
||||
await delay;
|
||||
}*/
|
||||
}
|
||||
|
||||
_logger.LogWarning("Crontab Watcher background service is stopped.");
|
||||
}
|
||||
|
|
@ -58,10 +58,24 @@ public class CrontabWatcher : BackgroundService
|
|||
// Get the current time
|
||||
var currentTime = DateTime.UtcNow;
|
||||
|
||||
// Get the last occurrence from the schedule
|
||||
var lastOccurrence = GetLastOccurrence(schedule);
|
||||
|
||||
// Get the next occurrence from the schedule
|
||||
var nextOccurrence = schedule.GetNextOccurrence(currentTime.AddSeconds(-1));
|
||||
|
||||
// Check if the current time matches the schedule
|
||||
// Get the previous occurrence from the execution log
|
||||
var previousOccurrence = item.LastExecutionTime;
|
||||
|
||||
// First check if this occurrence was already triggered
|
||||
if (previousOccurrence.HasValue &&
|
||||
previousOccurrence.Value >= lastOccurrence &&
|
||||
previousOccurrence.Value < nextOccurrence.AddSeconds(1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Then check if the current time matches the schedule
|
||||
bool matches = currentTime >= nextOccurrence && currentTime < nextOccurrence.AddSeconds(1);
|
||||
|
||||
if (matches)
|
||||
|
|
@ -72,9 +86,21 @@ public class CrontabWatcher : BackgroundService
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning($"Error when running cron task ({item.ConversationId}, {item.Title}, {item.Cron}): {ex.Message}\r\n{ex.InnerException}");
|
||||
_logger.LogError($"Error when running cron task ({item.Title}, {item.Cron}): {ex.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime GetLastOccurrence(CrontabSchedule schedule)
|
||||
{
|
||||
var nextOccurrence = schedule.GetNextOccurrence(DateTime.UtcNow);
|
||||
var afterNextOccurrence = schedule.GetNextOccurrence(nextOccurrence);
|
||||
var interval = afterNextOccurrence - nextOccurrence;
|
||||
if (interval.TotalMinutes < 10)
|
||||
{
|
||||
throw new ArgumentException("The minimum interval must be at least 10 minutes.");
|
||||
}
|
||||
return nextOccurrence - interval;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ public class RuleEngine : IRuleEngine
|
|||
{
|
||||
var conv = await convService.NewConversation(new Conversation
|
||||
{
|
||||
Channel = trigger.Channel,
|
||||
Title = data,
|
||||
AgentId = agent.Id
|
||||
});
|
||||
|
||||
|
|
@ -52,7 +54,7 @@ public class RuleEngine : IRuleEngine
|
|||
|
||||
var states = new List<MessageState>
|
||||
{
|
||||
new("channel", ConversationChannel.Database),
|
||||
new("channel", trigger.Channel),
|
||||
new("channel_id", trigger.EntityId)
|
||||
};
|
||||
convService.SetConversationId(conv.Id, states);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
namespace BotSharp.Core.Rules.Triggers;
|
||||
|
||||
public interface IRuleConfig
|
||||
{
|
||||
}
|
||||
|
|
@ -47,6 +47,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BotSharp.Core.Rules\BotSharp.Core.Rules.csproj" />
|
||||
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -160,16 +160,4 @@ public class AgentController : ControllerBase
|
|||
}
|
||||
return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList();
|
||||
}
|
||||
|
||||
[HttpGet("/agent/rule/options")]
|
||||
public IEnumerable<AgentRule> GetAgentRuleOptions()
|
||||
{
|
||||
var rules = new List<AgentRule>();
|
||||
var hooks = _services.GetServices<IAgentRuleHook>();
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
hook.AddRules(rules);
|
||||
}
|
||||
return rules.Where(x => !string.IsNullOrWhiteSpace(x.TriggerName)).OrderBy(x => x.TriggerName).ToList();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Core.Rules.Triggers;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class RulesController
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public RulesController(
|
||||
IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
[HttpGet("/rule/triggers")]
|
||||
public IEnumerable<AgentRule> GetRuleTriggers()
|
||||
{
|
||||
var triggers = _services.GetServices<IRuleTrigger>();
|
||||
return triggers.Select(x => new AgentRule
|
||||
{
|
||||
TriggerName = x.GetType().Name
|
||||
}).OrderBy(x => x.TriggerName).ToList();
|
||||
}
|
||||
|
||||
[HttpGet("/rule/formalization")]
|
||||
public async Task<string> GetFormalizedRuleDefinition([FromBody] AgentRule rule)
|
||||
{
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue