Skip to content

Commit

Permalink
version 2.0.0: names changed, OnBeforeRun/OnAfterRun methods
Browse files Browse the repository at this point in the history
  • Loading branch information
justdmitry committed Feb 5, 2016
1 parent 185c817 commit 9e1396f
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 39 deletions.
21 changes: 17 additions & 4 deletions README.md
Expand Up @@ -11,10 +11,10 @@ Written for **ASP.NET vNext** (ASP.NET 5, ASP.NET Core 1).
## Main features

* Start and Stop you task at any time;
* First run (after Start) is delayed at random value (10-30 sec, customizable) to prevent app delay during statup;
* First run (after Start) is delayed at random value (10-30 sec, customizable) to prevent app freeze during statup;
* Run "immediately" (without waiting for next scheduled time);
* Change run interval while running;
* Task `Status` property (extendable) contains:
* `RunStatus` property (extendable) contains:
* last/next run times;
* last run result (success / exception);
* last success run time;
Expand All @@ -25,15 +25,15 @@ Written for **ASP.NET vNext** (ASP.NET 5, ASP.NET Core 1).

### 1. Create new task class

public class MyFirstTask : TaskBase<TaskStatus>
public class MyFirstTask : TaskBase<TaskRunStatus>
{
public MyFirstTask(ILoggerFactory loggerFactory, IServiceScopeFactory serviceScopeFactory)
: base(loggerFactory, TimeSpan.FromMinutes(5), serviceScopeFactory)
{
// Nothing
}

protected override void Run(IServiceProvider serviceProvider, TaskStatus state)
protected override void Run(IServiceProvider serviceProvider, TaskRunStatus runStatus)
{
// Place your code here
}
Expand Down Expand Up @@ -61,3 +61,16 @@ And viola! Your task will run every 5 minutes (second param when calling :base c
## Installation

Use NuGet package [RecurrentTasks](https://www.nuget.org/packages/RecurrentTasks/)

### Dependencies

* Microsoft.Extensions.Logging.Abstractions
* Microsoft.Extensions.DependencyInjection.Abstractions

## Version history

* 2.0.0 (Feb 5, 2016)
* Class/method/property names changed. Incompatible update - major version bump.
* New overridable methods `OnBeforeRun`, `OnAfterRunSuccess`, `OnAfterRunFail`
* 1.0.0 (Feb 4, 2016)
* Initial release - our internal classes goes opensource
4 changes: 2 additions & 2 deletions sample/RecurrentTasks.Sample/SampleTask.cs
Expand Up @@ -5,7 +5,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

public class SampleTask : TaskBase<TaskStatus>
public class SampleTask : TaskBase<TaskRunStatus>
{
public List<string> Messages { get; } = new List<string>();

Expand All @@ -15,7 +15,7 @@ public SampleTask(ILoggerFactory loggerFactory, IServiceScopeFactory serviceScop
// Nothing
}

protected override void Run(IServiceProvider serviceProvider, TaskStatus state)
protected override void Run(IServiceProvider serviceProvider, TaskRunStatus runStatus)
{
Messages.Add(string.Format("Run at: {0}", DateTimeOffset.Now));
}
Expand Down
12 changes: 6 additions & 6 deletions sample/RecurrentTasks.Sample/Views/Home/Index.cshtml
Expand Up @@ -6,14 +6,14 @@
<dt>IsStarted</dt>
<dd>@myTask.IsStarted</dd>

<dt>Status.LastRunResult</dt>
<dd>@myTask.Status.LastRunResult</dd>
<dt>RunStatus.LastResult</dt>
<dd>@myTask.RunStatus.LastResult</dd>

<dt>Status.LastRunTime</dt>
<dd>@myTask.Status.LastRunTime</dd>
<dt>RunStatus.LastRunTime</dt>
<dd>@myTask.RunStatus.LastRunTime</dd>

<dt>Status.NextRunTime</dt>
<dd>@myTask.Status.NextRunTime (in @(myTask.Status.NextRunTime.Subtract(DateTime.Now)))</dd>
<dt>RunStatus.NextRunTime</dt>
<dd>@myTask.RunStatus.NextRunTime (in @(myTask.RunStatus.NextRunTime.Subtract(DateTime.Now)))</dd>
</dl>

<form method="post">
Expand Down
2 changes: 1 addition & 1 deletion src/RecurrentTasks/ITask.cs
Expand Up @@ -27,7 +27,7 @@ public interface ITask
/// <summary>
/// Information about task result (last run time, last exception, etc)
/// </summary>
TaskStatus Status { get; }
TaskRunStatus RunStatus { get; }

/// <summary>
/// Interval between runs
Expand Down
73 changes: 53 additions & 20 deletions src/RecurrentTasks/TaskBase.cs
Expand Up @@ -7,7 +7,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

public abstract class TaskBase<TState> : ITask where TState : TaskStatus, new()
public abstract class TaskBase<TRunStatus> : ITask where TRunStatus : TaskRunStatus, new()
{
private static readonly Random Random = new Random();

Expand All @@ -25,12 +25,12 @@ public TaskBase(ILoggerFactory loggerFactory, TimeSpan interval, IServiceScopeFa
Logger = loggerFactory.CreateLogger(this.GetType().FullName);
Interval = interval;
ServiceScopeFactory = serviceScopeFactory;
Status = new TState();
RunStatus = new TRunStatus();
}

TaskStatus ITask.Status { get { return Status; } }
TaskRunStatus ITask.RunStatus { get { return RunStatus; } }

public TState Status { get; private set; }
public TRunStatus RunStatus { get; protected set; }

public bool IsStarted
{
Expand Down Expand Up @@ -96,11 +96,11 @@ protected void MainLoop(TimeSpan initialTimeout)
while (true)
{
Logger.LogDebug("Sleeping for {0}...", sleepInterval);
Status.NextRunTime = DateTimeOffset.Now.Add(sleepInterval);
RunStatus.NextRunTime = DateTimeOffset.Now.Add(sleepInterval);
var signaled = WaitHandle.WaitAny(events, sleepInterval);
if (signaled == 0) // индекс сработавшего. нулевой это breakEvent
if (signaled == 0) // index of signalled. zero is for 'breakEvent'
{
// значит закругляемся
// must stop and quit
Logger.LogWarning("BreakEvent is set, stopping...");
mainTask = null;
break;
Expand All @@ -122,29 +122,38 @@ protected void MainLoop(TimeSpan initialTimeout)

try
{
OnBeforeRun();

IsRunningRightNow = true;

Status.LastRunTime = DateTimeOffset.Now;
RunStatus.LastRunTime = DateTimeOffset.Now;

Logger.LogInformation("Calling Run()...");
Run(scope.ServiceProvider, Status);
Run(scope.ServiceProvider, RunStatus);
Logger.LogInformation("Done.");

Status.LastRunResult = TaskRunResult.Success;
Status.LastSuccessTime = DateTimeOffset.Now;
Status.FirstFail = DateTimeOffset.MinValue;
Status.FailsCount = 0;
RunStatus.LastResult = TaskRunResult.Success;
RunStatus.LastSuccessTime = DateTimeOffset.Now;
RunStatus.FirstFailTime = DateTimeOffset.MinValue;
RunStatus.FailsCount = 0;
RunStatus.LastException = null;
IsRunningRightNow = false;

OnAfterRunSuccess();
}
catch (Exception ex)
{
Logger.LogWarning("Ooops, error (ignoring):", ex);
Status.LastRunResult = TaskRunResult.Fail;
Status.LastException = ex;
if (Status.FailsCount == 0)
Logger.LogWarning("Ooops, error (ignoring, see RunStatus.LastException):", ex);
RunStatus.LastResult = TaskRunResult.Fail;
RunStatus.LastException = ex;
if (RunStatus.FailsCount == 0)
{
Status.FirstFail = DateTimeOffset.Now;
RunStatus.FirstFailTime = DateTimeOffset.Now;
}
Status.FailsCount++;
RunStatus.FailsCount++;
IsRunningRightNow = false;

OnAfterRunFail();
}
finally
{
Expand All @@ -156,6 +165,30 @@ protected void MainLoop(TimeSpan initialTimeout)
Logger.LogInformation("MainLoop() finished.");
}

protected abstract void Run(IServiceProvider serviceProvider, TState state);
protected abstract void Run(IServiceProvider serviceProvider, TRunStatus runStatus);

/// <summary>
/// Called before Run() is called (even before IsRunningRightNow set to true)
/// </summary>
protected virtual void OnBeforeRun()
{
// nothing
}

/// <summary>
/// Called after Run() sucessfully finished (after IsRunningRightNow set to false)
/// </summary>
protected virtual void OnAfterRunSuccess()
{
// nothing
}

/// <summary>
/// Called after Run() falied (after IsRunningRightNow set to false)
/// </summary>
protected virtual void OnAfterRunFail()
{
// nothing
}
}
}
Expand Up @@ -2,15 +2,15 @@
{
using System;

public class TaskStatus
public class TaskRunStatus
{
public TaskRunResult LastRunResult { get; set; }
public TaskRunResult LastResult { get; set; }

public DateTimeOffset LastRunTime { get; set; }

public DateTimeOffset LastSuccessTime { get; set; }

public DateTimeOffset FirstFail { get; set; }
public DateTimeOffset FirstFailTime { get; set; }

public int FailsCount { get; set; }

Expand Down
3 changes: 2 additions & 1 deletion src/RecurrentTasks/project.json
@@ -1,11 +1,12 @@
{
"version": "1.0.0",
"version": "2.0.0",
"title": "RecurrentTasks",
"description": "RecurrentTasks for .NET allows you to run simple recurrent background tasks with specific intervals, without complex frameworks, persistance, etc...",
"authors": [ "Dmitry Popov" ],
"tags": [ "task", "job", "recurrent", "recurring", "aspnetcore" ],
"projectUrl": "https://github.com/justdmitry/RecurrentTasks",
"copyright": "Dmitry Popov, 2016",
"releaseNotes": "Renames in classes/methods/properties, OnBefore/OnAfterRun overridable methods",
"licenseUrl": "https://github.com/justdmitry/RecurrentTasks/blob/master/LICENSE",
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions test/RecurrentTasks.Tests/SampleTask.cs
Expand Up @@ -5,7 +5,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

public class SampleTask : TaskBase<TaskStatus>
public class SampleTask : TaskBase<TaskRunStatus>
{
public readonly ManualResetEventSlim TaskRunCalled = new ManualResetEventSlim(false);

Expand All @@ -19,7 +19,7 @@ public SampleTask(ILoggerFactory loggerFactory, TimeSpan interval, IServiceScope
// Nothing
}

protected override void Run(IServiceProvider serviceProvider, TaskStatus state)
protected override void Run(IServiceProvider serviceProvider, TaskRunStatus runStatus)
{
TaskRunCalled.Set();
if (MustThrowError)
Expand Down

0 comments on commit 9e1396f

Please sign in to comment.