Skip to content

Commit

Permalink
Add Recurring Tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
mythz committed Aug 16, 2024
1 parent 308b1f2 commit e9504b2
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 2 deletions.
60 changes: 60 additions & 0 deletions MyApp.ServiceInterface/App/LogCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Net.Mail;
using Microsoft.Extensions.Logging;
using MyApp.Data;
using ServiceStack;

namespace MyApp.ServiceInterface.App;

public class LogRequest
{
public string Message { get; set; }
}

public class LogCommand(ILogger<LogCommand> log) : IAsyncCommand<LogRequest>
{
private static int count = 0;

public Task ExecuteAsync(LogRequest request)
{
Interlocked.Increment(ref count);
log.LogInformation("Log {Count}: {Message}", count, request.Message);
return Task.CompletedTask;
}
}

public class SendEmailCommand(ILogger<LogCommand> log, SmtpConfig config) : IAsyncCommand<SendEmail>
{
private static int count = 0;

public Task ExecuteAsync(SendEmail request)
{
Interlocked.Increment(ref count);
log.LogInformation("Sending {Count} email to {Email} with subject {Subject}", count, request.To, request.Subject);

using var client = new SmtpClient(config.Host, config.Port);
client.Credentials = new System.Net.NetworkCredential(config.Username, config.Password);
client.EnableSsl = true;

// If DevToEmail is set, send all emails to that address instead
var emailTo = config.DevToEmail != null
? new MailAddress(config.DevToEmail)
: new MailAddress(request.To, request.ToName);

var emailFrom = new MailAddress(config.FromEmail, config.FromName);

var msg = new MailMessage(emailFrom, emailTo)
{
Subject = request.Subject,
Body = request.BodyHtml ?? request.BodyText,
IsBodyHtml = request.BodyHtml != null,
};

if (config.Bcc != null)
{
msg.Bcc.Add(new MailAddress(config.Bcc));
}

client.Send(msg);
return Task.CompletedTask;
}
}
63 changes: 63 additions & 0 deletions MyApp/Configure.BackgroundJobs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using MyApp.Data;
using MyApp.ServiceInterface.App;
using MyApp.ServiceModel;
using ServiceStack.Jobs;

[assembly: HostingStartup(typeof(MyApp.ConfigureBackgroundJobs))]

namespace MyApp;

public class ConfigureBackgroundJobs : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices(services => {
services.AddPlugin(new CommandsFeature());
services.AddPlugin(new BackgroundsJobFeature());
services.AddHostedService<JobsHostedService>();
}).ConfigureAppHost(afterAppHostInit:appHost =>
{
var jobs = appHost.Resolve<IBackgroundJobs>();
jobs.RecurringCommand<LogCommand>("Every Minute", Schedule.EveryMinute,
new LogRequest { Message = "Hello from Recurring Command" });
jobs.RecurringCommand<SendEmailCommand>("Every 8 hours", Schedule.Interval(TimeSpan.FromHours(8)),
new SendEmail
{
To = "[email protected]",
Subject = "Hi from recurring command",
BodyText = "Test email from a Scheduled Tasks recurring command"
});
jobs.RecurringApi("DbWrites Hourly", Schedule.Hourly,
new DbWrites {
PeriodicTasks = new PeriodicTasks { PeriodicFrequency = PeriodicFrequency.Hourly }
});
});
}

public class JobsHostedService(ILogger<JobsHostedService> log, IBackgroundJobs jobs) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await jobs.StartAsync(stoppingToken);

using var timer = new PeriodicTimer(TimeSpan.FromSeconds(3));
var tick = 0;
var errors = 0;
while (!stoppingToken.IsCancellationRequested && await timer.WaitForNextTickAsync(stoppingToken))
{
try
{
tick++;
await jobs.TickAsync();
}
catch (Exception e)
{
log.LogError(e, "JOBS {Errors}/{Tick} Error in JobsHostedService: {Message}",
++errors, tick, e.Message);
}
}
}
}
5 changes: 3 additions & 2 deletions MyApp/Configure.Mq.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public void Configure(IWebHostBuilder builder) => builder
services.AddSingleton<IMessageProducer>(c => c.GetRequiredService<IMessageService>().MessageFactory.CreateMessageProducer());
services.AddSingleton<ModelWorkerQueue>();
services.AddSingleton<WorkerAnswerNotifier>();
services.AddPlugin(new CommandsFeature());
services.AddHostedService<TimedHostedService>();
// services.AddPlugin(new CommandsFeature());
// Use ServiceStack.Jobs Recurring Tasks instead
// services.AddHostedService<TimedHostedService>();
})
.ConfigureAppHost(afterAppHostInit: appHost => {
var mqService = appHost.Resolve<IMessageService>();
Expand Down
1 change: 1 addition & 0 deletions MyApp/MyApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<PackageReference Include="ServiceStack.Extensions" Version="8.*" />
<PackageReference Include="ServiceStack.Server" Version="8.*" />
<PackageReference Include="ServiceStack.Aws" Version="8.*" />
<PackageReference Include="ServiceStack.Jobs" Version="8.*" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit e9504b2

Please sign in to comment.