Skip to content

Commit 9d42f6a

Browse files
committed
Many improvements to distributed cron jobs
1 parent 808e517 commit 9d42f6a

17 files changed

+762
-396
lines changed

Foundatio.All.sln

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Foundatio.JsonNet", "src\Fo
3434
EndProject
3535
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Foundatio.Utf8Json", "src\Foundatio.Utf8Json\Foundatio.Utf8Json.csproj", "{44A5A11C-4D9E-4219-9E56-46F07E37A3B0}"
3636
EndProject
37-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Foundatio.Extensions.Hosting", "src\Foundatio.Extensions.Hosting\Foundatio.Extensions.Hosting.csproj", "{FC503293-E2AD-4FE8-856E-F2605D0422D1}"
38-
EndProject
3937
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Foundatio.MessagePack", "src\Foundatio.MessagePack\Foundatio.MessagePack.csproj", "{1D0CF7B3-D0B3-4739-A280-5C0822169E08}"
4038
EndProject
4139
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Foundatio.AWS", "..\Foundatio.AWS\src\Foundatio.AWS\Foundatio.AWS.csproj", "{2D2DBEA1-A199-4311-8F29-CF7AD5EE1C47}"
@@ -106,6 +104,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foundatio.Parsers.SqlQuerie
106104
EndProject
107105
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foundatio.Parsers.SqlQueries", "..\Foundatio.Parsers\src\Foundatio.Parsers.SqlQueries\Foundatio.Parsers.SqlQueries.csproj", "{DC95F757-B081-48E5-95AE-E8AF2A9FEB63}"
108106
EndProject
107+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foundatio.AppHost", "samples\Foundatio.AppHost\Foundatio.AppHost.csproj", "{91529E2E-1E82-4D4C-9543-C0FB9DD783CE}"
108+
EndProject
109+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foundatio.Extensions.Hosting", "src\Foundatio.Extensions.Hosting\Foundatio.Extensions.Hosting.csproj", "{2574F5D9-878D-42C1-A60D-08CB55C1A6BB}"
110+
EndProject
109111
Global
110112
GlobalSection(SolutionConfigurationPlatforms) = preSolution
111113
Debug|Any CPU = Debug|Any CPU
@@ -140,10 +142,6 @@ Global
140142
{44A5A11C-4D9E-4219-9E56-46F07E37A3B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
141143
{44A5A11C-4D9E-4219-9E56-46F07E37A3B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
142144
{44A5A11C-4D9E-4219-9E56-46F07E37A3B0}.Release|Any CPU.Build.0 = Release|Any CPU
143-
{FC503293-E2AD-4FE8-856E-F2605D0422D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
144-
{FC503293-E2AD-4FE8-856E-F2605D0422D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
145-
{FC503293-E2AD-4FE8-856E-F2605D0422D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
146-
{FC503293-E2AD-4FE8-856E-F2605D0422D1}.Release|Any CPU.Build.0 = Release|Any CPU
147145
{1D0CF7B3-D0B3-4739-A280-5C0822169E08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
148146
{1D0CF7B3-D0B3-4739-A280-5C0822169E08}.Debug|Any CPU.Build.0 = Debug|Any CPU
149147
{1D0CF7B3-D0B3-4739-A280-5C0822169E08}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -284,6 +282,14 @@ Global
284282
{DC95F757-B081-48E5-95AE-E8AF2A9FEB63}.Debug|Any CPU.Build.0 = Debug|Any CPU
285283
{DC95F757-B081-48E5-95AE-E8AF2A9FEB63}.Release|Any CPU.ActiveCfg = Release|Any CPU
286284
{DC95F757-B081-48E5-95AE-E8AF2A9FEB63}.Release|Any CPU.Build.0 = Release|Any CPU
285+
{91529E2E-1E82-4D4C-9543-C0FB9DD783CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
286+
{91529E2E-1E82-4D4C-9543-C0FB9DD783CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
287+
{91529E2E-1E82-4D4C-9543-C0FB9DD783CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
288+
{91529E2E-1E82-4D4C-9543-C0FB9DD783CE}.Release|Any CPU.Build.0 = Release|Any CPU
289+
{2574F5D9-878D-42C1-A60D-08CB55C1A6BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
290+
{2574F5D9-878D-42C1-A60D-08CB55C1A6BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
291+
{2574F5D9-878D-42C1-A60D-08CB55C1A6BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
292+
{2574F5D9-878D-42C1-A60D-08CB55C1A6BB}.Release|Any CPU.Build.0 = Release|Any CPU
287293
EndGlobalSection
288294
GlobalSection(SolutionProperties) = preSolution
289295
HideSolutionNode = FALSE
@@ -312,6 +318,7 @@ Global
312318
{0B2C6825-972B-4B52-84A6-81C668FFCD5C} = {A1DFF80C-113F-4FEC-84BB-1E3790FB410F}
313319
{F25CB5A4-DE0E-4476-9736-DCD619BC8960} = {70515E66-DAF8-4D18-8F8F-8A2934171AA9}
314320
{FECAABE4-7B4B-4F70-A539-2B2ED4638AFA} = {70515E66-DAF8-4D18-8F8F-8A2934171AA9}
321+
{91529E2E-1E82-4D4C-9543-C0FB9DD783CE} = {A1DFF80C-113F-4FEC-84BB-1E3790FB410F}
315322
EndGlobalSection
316323
GlobalSection(ExtensibilityGlobals) = postSolution
317324
SolutionGuid = {BD75F5C6-658B-40DF-A8F6-91C3EB76DAAA}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Foundatio.AppHost.Extensions;
2+
3+
public static class ImageTags
4+
{
5+
public const string Redis = "7.4-alpine";
6+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using Microsoft.Extensions.Diagnostics.HealthChecks;
2+
using StackExchange.Redis;
3+
4+
namespace Foundatio.AppHost.Extensions;
5+
6+
public static class RedisExtensions
7+
{
8+
public static IResourceBuilder<RedisResource> WithClearCommand(
9+
this IResourceBuilder<RedisResource> builder)
10+
{
11+
builder.WithCommand(
12+
"clear-cache",
13+
"Clear Cache",
14+
async _ =>
15+
{
16+
var redisConnectionString = await builder.Resource.GetConnectionStringAsync() ??
17+
throw new InvalidOperationException("Unable to get the Redis connection string.");
18+
19+
await using var connection = await ConnectionMultiplexer.ConnectAsync(redisConnectionString);
20+
21+
await connection.GetDatabase().ExecuteAsync("FLUSHALL");
22+
23+
return CommandResults.Success();
24+
},
25+
new CommandOptions
26+
{
27+
UpdateState = context => context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy ? ResourceCommandState.Enabled : ResourceCommandState.Disabled
28+
});
29+
return builder;
30+
}
31+
}

samples/Foundatio.AppHost/Foundatio.AppHost.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313

1414
<ItemGroup>
1515
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.3.0" />
16+
<PackageReference Include="Aspire.Hosting.Redis" Version="9.3.0" />
1617
</ItemGroup>
1718

1819
<ItemGroup>
19-
<ProjectReference Include="..\Foundatio.HostingSample\Foundatio.HostingSample.csproj" />
20+
<ProjectReference Include="..\Foundatio.HostingSample\Foundatio.HostingSample.csproj" />
2021
</ItemGroup>
2122

2223
</Project>

samples/Foundatio.AppHost/Program.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
1+
using Foundatio.AppHost.Extensions;
12
using Projects;
3+
#pragma warning disable ASPIREPROXYENDPOINTS001
24

35
var builder = DistributedApplication.CreateBuilder(args);
46

5-
builder.AddProject<Foundatio_HostingSample>("HostingSample")
7+
var cache = builder.AddRedis("Redis", port: 6379)
8+
.WithContainerName("Foundatio-Redis")
9+
.WithImageTag(ImageTags.Redis)
10+
.WithEndpointProxySupport(false)
11+
.WithClearCommand()
12+
.WithRedisInsight(b => b.WithEndpointProxySupport(false).WithContainerName("Foundatio-RedisInsight")
13+
.WithUrlForEndpoint("http", u => u.DisplayText = "Cache"));
14+
15+
builder.AddProject<Foundatio_HostingSample>("Foundatio-HostingSample")
616
.WithExternalHttpEndpoints()
7-
.WithArgs("all");
17+
.WithReplicas(3)
18+
.WithReference(cache)
19+
.WaitFor(cache)
20+
.WithArgs("all")
21+
.WithUrls(u =>
22+
{
23+
u.Urls.Clear();
24+
u.Urls.Add(new ResourceUrlAnnotation { Url = "/jobstatus", DisplayText = "Job Status", Endpoint = u.GetEndpoint("http") });
25+
u.Urls.Add(new ResourceUrlAnnotation { Url = "/runjob", DisplayText = "Run Job", Endpoint = u.GetEndpoint("http") });
26+
});
827

928
builder.Build().Run();

samples/Foundatio.HostingSample/Foundatio.HostingSample.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
55
<IsPackable>False</IsPackable>
6+
<EnableRedis>false</EnableRedis>
7+
<DefineConstants Condition="'$(EnableRedis)' == 'true'">REDIS</DefineConstants>
68
</PropertyGroup>
79

810
<ItemGroup>
911
<ProjectReference Include="..\..\src\Foundatio.Extensions.Hosting\Foundatio.Extensions.Hosting.csproj" />
1012
<ProjectReference Include="..\..\src\Foundatio\Foundatio.csproj" />
13+
<ProjectReference Include="..\..\..\Foundatio.Redis\src\Foundatio.Redis\Foundatio.Redis.csproj" Condition="'$(EnableRedis)' == 'true'" />
1114
</ItemGroup>
1215

1316
<ItemGroup>
14-
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
15-
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
16-
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
1717
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
1818
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
1919
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />

samples/Foundatio.HostingSample/Jobs/EveryMinuteJob.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
using System;
22
using System.Threading;
33
using System.Threading.Tasks;
4+
using Foundatio.Caching;
45
using Foundatio.Jobs;
56
using Microsoft.Extensions.Logging;
67

78
namespace Foundatio.HostingSample;
89

910
public class EveryMinuteJob : IJob
1011
{
12+
private readonly ICacheClient _cacheClient;
1113
private readonly ILogger _logger;
1214

13-
public EveryMinuteJob(ILoggerFactory loggerFactory)
15+
public EveryMinuteJob(ILoggerFactory loggerFactory, ICacheClient cacheClient)
1416
{
17+
_cacheClient = cacheClient;
1518
_logger = loggerFactory.CreateLogger<EveryMinuteJob>();
1619
}
1720

1821
public async Task<JobResult> RunAsync(CancellationToken cancellationToken = default)
1922
{
20-
_logger.LogInformation("EveryMinuteJob Run Thread={ManagedThreadId}", Thread.CurrentThread.ManagedThreadId);
23+
var runCount = await _cacheClient.IncrementAsync("EveryMinuteJob");
2124

22-
await Task.Delay(TimeSpan.FromSeconds(4));
25+
_logger.LogInformation("EveryMinuteJob Run Count={Count} Thread={ManagedThreadId}", runCount, Thread.CurrentThread.ManagedThreadId);
26+
27+
await Task.Delay(TimeSpan.FromSeconds(30));
28+
29+
_logger.LogInformation("EveryMinuteJob Complete");
2330

2431
return JobResult.Success;
2532
}

0 commit comments

Comments
 (0)