-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
81 lines (69 loc) · 3.95 KB
/
Copy pathProgram.cs
File metadata and controls
81 lines (69 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
using KatzuoOgust.Looop;
// ── Once ──────────────────────────────────────────────────────────────────────
Console.WriteLine("=== Once ===");
await Loop.RunAsync(
_ => { Console.WriteLine("Fired once"); return Task.CompletedTask; },
Trigger.Once());
// ── After ─────────────────────────────────────────────────────────────────────
Console.WriteLine("\n=== After 200ms ===");
await Loop.RunAsync(
_ => { Console.WriteLine("Fired after delay"); return Task.CompletedTask; },
Trigger.After(TimeSpan.FromMilliseconds(200)));
// ── Every (with cancellation) ─────────────────────────────────────────────────
Console.WriteLine("\n=== Every 100ms for ~400ms ===");
using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(400));
int count = 0;
await Loop.RunAsync(
_ => { Console.WriteLine($" tick {++count}"); return Task.CompletedTask; },
Trigger.Every(TimeSpan.FromMilliseconds(100)),
cancellationToken: cts.Token);
// ── Cron ──────────────────────────────────────────────────────────────────────
Console.WriteLine("\n=== Cron: next @hourly occurrence ===");
var next = await Trigger.Cron("@hourly").NextAsync();
Console.WriteLine($" Next @hourly tick: {next:HH:mm:ss} UTC");
// ── WhenAny ───────────────────────────────────────────────────────────────────
Console.WriteLine("\n=== WhenAny: pick earliest of 50ms / 200ms (fires 3 times) ===");
using var cts2 = new CancellationTokenSource(TimeSpan.FromMilliseconds(250));
int tick = 0;
await Loop.RunAsync(
_ => { Console.WriteLine($" WhenAny tick {++tick}"); return Task.CompletedTask; },
Trigger.WhenAny(
Trigger.Every(TimeSpan.FromMilliseconds(50)),
Trigger.Every(TimeSpan.FromMilliseconds(200))),
cancellationToken: cts2.Token);
// ── ErrorPolicy.Continue ──────────────────────────────────────────────────────
Console.WriteLine("\n=== ErrorPolicy.Continue: errors are swallowed ===");
using var cts3 = new CancellationTokenSource(TimeSpan.FromMilliseconds(250));
int run = 0;
await Loop.RunAsync(
_ =>
{
run++;
Console.WriteLine($" attempt {run}");
if (run % 2 == 0) throw new Exception("even runs fail (swallowed)");
return Task.CompletedTask;
},
Trigger.Every(TimeSpan.FromMilliseconds(60)),
ErrorPolicy.Continue,
cts3.Token);
// ── IJob ──────────────────────────────────────────────────────────────────────
Console.WriteLine("\n=== IJob implementation ===");
await Loop.RunAsync(new CountdownJob(3));
Console.WriteLine("\nDone.");
sealed class CountdownJob(int limit) : IJob
{
private readonly ITrigger _trigger = Trigger.Every(TimeSpan.FromMilliseconds(50));
private int _count;
public ValueTask<DateTimeOffset?> NextAsync(DateTimeOffset? lastRunAt = null, CancellationToken ct = default) =>
_count >= limit ? new(default(DateTimeOffset?)) : _trigger.NextAsync(lastRunAt, ct);
public Task HandleAsync(CancellationToken ct)
{
Console.WriteLine($" CountdownJob tick {++_count}/{limit}");
return Task.CompletedTask;
}
public ValueTask HandleErrorAsync(Exception ex, CancellationToken ct)
{
Console.WriteLine($" Error (continuing): {ex.Message}");
return ValueTask.CompletedTask;
}
}