Skip to content

Commit d0b9ea9

Browse files
authored
Merge pull request #1230 from adenchen123/master
new crontab api for scheduling every one minute
2 parents 7d92706 + 80f68c8 commit d0b9ea9

File tree

7 files changed

+106
-3
lines changed

7 files changed

+106
-3
lines changed

src/Infrastructure/BotSharp.Abstraction/Crontab/Models/CrontabItem.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,17 @@ public class CrontabItem : ScheduleTaskArgs
2929
[JsonPropertyName("created_time")]
3030
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
3131

32+
[JsonPropertyName("trigger_type")]
33+
public CronTabItemTriggerType TriggerType { get; set; } = CronTabItemTriggerType.BackgroundWatcher;
34+
3235
public override string ToString()
3336
{
3437
return $"{Title}: {Description} [AgentId: {AgentId}, UserId: {UserId}]";
3538
}
3639
}
40+
41+
public enum CronTabItemTriggerType
42+
{
43+
BackgroundWatcher,
44+
OpenAPI
45+
}

src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabEventSubscription.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
2929
var subscriber = scope.ServiceProvider.GetRequiredService<IEventSubscriber>();
3030
var cron = scope.ServiceProvider.GetRequiredService<ICrontabService>();
3131
var crons = await cron.GetCrontable();
32-
foreach (var item in crons)
32+
var allowedCrons = crons.Where(cron => cron.TriggerType == CronTabItemTriggerType.BackgroundWatcher).ToList();
33+
foreach (var item in allowedCrons)
3334
{
3435
_ = Task.Run(async () =>
3536
{
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using NCrontab;
2+
3+
namespace BotSharp.Core.Crontab.Services
4+
{
5+
public static class CrontabItemExtension
6+
{
7+
public static bool CheckNextOccurrenceEveryOneMinute(this CrontabItem item)
8+
{
9+
// strip seconds from cron expression
10+
item.Cron = string.Join(" ", item.Cron.Split(' ').TakeLast(5));
11+
var schedule = CrontabSchedule.Parse(item.Cron, new CrontabSchedule.ParseOptions
12+
{
13+
IncludingSeconds = false // Ensure you account for seconds
14+
});
15+
16+
var currentTime = DateTime.UtcNow;
17+
var currentMinute = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day,
18+
currentTime.Hour, currentTime.Minute, 0, DateTimeKind.Utc);
19+
20+
var oneMinuteAgo = currentMinute.AddMinutes(-1);
21+
var nextOccurrence = schedule.GetNextOccurrence(oneMinuteAgo);
22+
23+
return nextOccurrence == currentMinute;
24+
}
25+
}
26+
}

src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ private async Task RunCronChecker(IServiceProvider services)
5858
{
5959
var cron = services.GetRequiredService<ICrontabService>();
6060
var crons = await cron.GetCrontable();
61+
var allowedCrons = crons.Where(cron => cron.TriggerType == CronTabItemTriggerType.BackgroundWatcher).ToList();
6162
var settings = services.GetRequiredService<CrontabSettings>();
6263
var publisher = services.GetService<IEventPublisher>();
6364

64-
foreach (var item in crons)
65+
foreach (var item in allowedCrons)
6566
{
6667
_logger.LogDebug($"[{DateTime.UtcNow}] Cron task ({item.Title}, {item.Cron}), Last Execution Time: {item.LastExecutionTime}");
6768

src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>$(TargetFramework)</TargetFramework>
@@ -35,6 +35,7 @@
3535
</ItemGroup>
3636

3737
<ItemGroup>
38+
<ProjectReference Include="..\BotSharp.Core.Crontab\BotSharp.Core.Crontab.csproj" />
3839
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
3940
<ProjectReference Include="..\BotSharp.Logger\BotSharp.Logger.csproj" />
4041
</ItemGroup>

src/Infrastructure/BotSharp.OpenAPI/Controllers/Crontab/CrontabController.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using BotSharp.Abstraction.Crontab;
2+
using BotSharp.Abstraction.Crontab.Models;
3+
using BotSharp.Core.Crontab.Services;
4+
using BotSharp.OpenAPI.Controllers.Crontab.Models;
25

36
namespace BotSharp.OpenAPI.Controllers;
47

@@ -42,4 +45,60 @@ public async Task<bool> RunCrontab(string name)
4245
return false;
4346
}
4447
}
48+
49+
/// <summary>
50+
/// As the Dkron job trigger API, run every 1 minutes
51+
/// </summary>
52+
/// <returns></returns>
53+
[HttpPost("/crontab/scheduling-per-minute")]
54+
public async Task<CrontabSchedulingResult> SchedulingCrontab()
55+
{
56+
var result = new CrontabSchedulingResult();
57+
var allowedCrons = await GetCrontabItems();
58+
59+
foreach (var item in allowedCrons)
60+
{
61+
if (item.CheckNextOccurrenceEveryOneMinute())
62+
{
63+
_logger.LogInformation("Crontab: {0}, One occurrence was matched, Beginning execution...", item.Title);
64+
Task.Run(() => ExecuteTimeArrivedItem(item, _services));
65+
result.OccurrenceMatchedItems.Add(item.Title);
66+
}
67+
}
68+
69+
await Task.Delay(1000);
70+
return result;
71+
}
72+
73+
private async Task<List<CrontabItem>> GetCrontabItems(string? title = null)
74+
{
75+
var crontabService = _services.GetRequiredService<ICrontabService>();
76+
var crons = await crontabService.GetCrontable();
77+
var allowedCrons = crons.Where(cron => cron.TriggerType == CronTabItemTriggerType.OpenAPI).ToList();
78+
79+
if (title is null)
80+
{
81+
return allowedCrons;
82+
}
83+
84+
return allowedCrons.Where(cron => cron.Title.IsEqualTo(title)).ToList();
85+
}
86+
87+
private async Task<bool> ExecuteTimeArrivedItem(CrontabItem item, IServiceProvider services)
88+
{
89+
try
90+
{
91+
using var scope = services.CreateScope();
92+
var crontabService = scope.ServiceProvider.GetRequiredService<ICrontabService>();
93+
_logger.LogInformation($"Start running crontab {item.Title}");
94+
await crontabService.ScheduledTimeArrived(item);
95+
_logger.LogInformation($"Complete running crontab {item.Title}");
96+
return true;
97+
}
98+
catch (Exception ex)
99+
{
100+
_logger.LogError(ex, $"Error when running crontab {item.Title}");
101+
return false;
102+
}
103+
}
45104
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace BotSharp.OpenAPI.Controllers.Crontab.Models;
2+
3+
public class CrontabSchedulingResult
4+
{
5+
public List<string> OccurrenceMatchedItems { get; set; } = new List<string>();
6+
}

0 commit comments

Comments
 (0)