Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ public class CrontabItem : ScheduleTaskArgs
[JsonPropertyName("created_time")]
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;

[JsonPropertyName("trigger_by_watcher")]
public bool TriggerByWatcher { get; set; } = true;

[JsonPropertyName("trigger_by_openapi")]
public bool TriggerByOpenAPI { get; set; }

public override string ToString()
{
return $"{Title}: {Description} [AgentId: {AgentId}, UserId: {UserId}]";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using NCrontab;

namespace BotSharp.Core.Crontab.Services
{
public static class CrontabItemExtension
{
public static bool CheckNextOccurrenceEveryOneMinute(this CrontabItem item)
{
// strip seconds from cron expression
item.Cron = string.Join(" ", item.Cron.Split(' ').TakeLast(5));
var schedule = CrontabSchedule.Parse(item.Cron, new CrontabSchedule.ParseOptions
{
IncludingSeconds = false // Ensure you account for seconds
});

var currentTime = DateTime.UtcNow;

// Check if there has been an execution point within the past minute.
var oneMinuteAgo = currentTime.AddMinutes(-1);
var nextOccurrenceFromPast = schedule.GetNextOccurrence(oneMinuteAgo);

// If the next execution point falls within the past minute up to the present, then it matches.
return nextOccurrenceFromPast > oneMinuteAgo && nextOccurrenceFromPast <= currentTime;
}
}
}
3 changes: 2 additions & 1 deletion src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(TargetFramework)</TargetFramework>
Expand Down Expand Up @@ -35,6 +35,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BotSharp.Core.Crontab\BotSharp.Core.Crontab.csproj" />
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
<ProjectReference Include="..\BotSharp.Logger\BotSharp.Logger.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using BotSharp.Abstraction.Crontab;
using BotSharp.Abstraction.Crontab.Models;
using BotSharp.Core.Crontab.Services;

namespace BotSharp.OpenAPI.Controllers;

Expand All @@ -20,25 +22,63 @@ public CrontabController(
[HttpPost("/crontab/{name}")]
public async Task<bool> RunCrontab(string name)
{
var cron = _services.GetRequiredService<ICrontabService>();
var crons = await cron.GetCrontable();
var found = crons.FirstOrDefault(x => x.Title.IsEqualTo(name));
if (found == null)
var found = await GetCrontabItems(name);
if (found.IsNullOrEmpty())
{
_logger.LogWarning($"Cannnot find crontab {name}");
return false;
}

return await ExecuteTimeArrivedItem(found.First());
}

/// <summary>
/// As the Dkron job trigger API, run every 1 minutes
/// </summary>
/// <returns></returns>
[HttpPost("/crontab/scheduling-per-minute")]
public async Task SchedulingCrontab()
{
var allowedCrons = await GetCrontabItems();

foreach (var item in allowedCrons)
{
if (item.CheckNextOccurrenceEveryOneMinute())
{
_logger.LogInformation("Crontab: {0}, One occurrence was matched, Beginning execution...", item.Title);
Task.Run(() => ExecuteTimeArrivedItem(item));
}
}
}

private async Task<List<CrontabItem>> GetCrontabItems(string? title = null)
{
var crontabService = _services.GetRequiredService<ICrontabService>();
var crons = await crontabService.GetCrontable();
var allowedCrons = crons.Where(cron => cron.TriggerByOpenAPI).ToList();

if (title is null)
{
return allowedCrons;
}

return allowedCrons.Where(cron => cron.Title.IsEqualTo(title)).ToList();
}

private async Task<bool> ExecuteTimeArrivedItem(CrontabItem item)
{
try
{
_logger.LogWarning($"Start running crontab {name}");
await cron.ScheduledTimeArrived(found);
_logger.LogWarning($"Complete running crontab {name}");
using var scope = _services.CreateScope();
var crontabService = scope.ServiceProvider.GetRequiredService<ICrontabService>();
_logger.LogWarning($"Start running crontab {item.Title}");
await crontabService.ScheduledTimeArrived(item);
_logger.LogWarning($"Complete running crontab {item.Title}");
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error when running crontab {name}");
_logger.LogError(ex, $"Error when running crontab {item.Title}");
return false;
}
}
Expand Down
Loading