Skip to content

Commit 5bcf757

Browse files
author
aden.chen
committed
new crontab api for scheduling every one minute
1 parent 0a50ebd commit 5bcf757

4 files changed

Lines changed: 82 additions & 9 deletions

File tree

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

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

32+
[JsonPropertyName("trigger_by_watcher")]
33+
public bool TriggerByWatcher { get; set; } = true;
34+
35+
[JsonPropertyName("trigger_by_openapi")]
36+
public bool TriggerByOpenAPI { get; set; }
37+
3238
public override string ToString()
3339
{
3440
return $"{Title}: {Description} [AgentId: {AgentId}, UserId: {UserId}]";
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+
18+
// Check if there has been an execution point within the past minute.
19+
var oneMinuteAgo = currentTime.AddMinutes(-1);
20+
var nextOccurrenceFromPast = schedule.GetNextOccurrence(oneMinuteAgo);
21+
22+
// If the next execution point falls within the past minute up to the present, then it matches.
23+
return nextOccurrenceFromPast > oneMinuteAgo && nextOccurrenceFromPast <= currentTime;
24+
}
25+
}
26+
}

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: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using BotSharp.Abstraction.Crontab;
2+
using BotSharp.Abstraction.Crontab.Models;
3+
using BotSharp.Core.Crontab.Services;
24

35
namespace BotSharp.OpenAPI.Controllers;
46

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

32+
return await ExecuteTimeArrivedItem(found.First());
33+
}
34+
35+
/// <summary>
36+
/// As the Dkron job trigger API, run every 1 minutes
37+
/// </summary>
38+
/// <returns></returns>
39+
[HttpPost("/crontab/scheduling-per-minute")]
40+
public async Task SchedulingCrontab()
41+
{
42+
var allowedCrons = await GetCrontabItems();
43+
44+
foreach (var item in allowedCrons)
45+
{
46+
if (item.CheckNextOccurrenceEveryOneMinute())
47+
{
48+
_logger.LogInformation("Crontab: {0}, One occurrence was matched, Beginning execution...", item.Title);
49+
Task.Run(() => ExecuteTimeArrivedItem(item));
50+
}
51+
}
52+
}
53+
54+
private async Task<List<CrontabItem>> GetCrontabItems(string? title = null)
55+
{
56+
var crontabService = _services.GetRequiredService<ICrontabService>();
57+
var crons = await crontabService.GetCrontable();
58+
var allowedCrons = crons.Where(cron => cron.TriggerByOpenAPI).ToList();
59+
60+
if (title is null)
61+
{
62+
return allowedCrons;
63+
}
64+
65+
return allowedCrons.Where(cron => cron.Title.IsEqualTo(title)).ToList();
66+
}
67+
68+
private async Task<bool> ExecuteTimeArrivedItem(CrontabItem item)
69+
{
3270
try
3371
{
34-
_logger.LogWarning($"Start running crontab {name}");
35-
await cron.ScheduledTimeArrived(found);
36-
_logger.LogWarning($"Complete running crontab {name}");
72+
using var scope = _services.CreateScope();
73+
var crontabService = scope.ServiceProvider.GetRequiredService<ICrontabService>();
74+
_logger.LogWarning($"Start running crontab {item.Title}");
75+
await crontabService.ScheduledTimeArrived(item);
76+
_logger.LogWarning($"Complete running crontab {item.Title}");
3777
return true;
3878
}
3979
catch (Exception ex)
4080
{
41-
_logger.LogError(ex, $"Error when running crontab {name}");
81+
_logger.LogError(ex, $"Error when running crontab {item.Title}");
4282
return false;
4383
}
4484
}

0 commit comments

Comments
 (0)