Skip to content

Commit

Permalink
Merge pull request #25 from TinkoffCreditSystems/feature/3
Browse files Browse the repository at this point in the history
Settings of repeat job after failed #3
  • Loading branch information
Bobreshovr authored Jul 30, 2019
2 parents 566d99e + d2ffb6c commit 6044603
Show file tree
Hide file tree
Showing 13 changed files with 376 additions and 89 deletions.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ public class SimpleInjectorJobScope : IJobScope
```

Then add `HorariumServer` (or `HorariumClient`):

```csharp
container.RegisterSingleton<IHorarium>(() =>
{
Expand All @@ -203,7 +204,57 @@ container.RegisterSingleton<IHorarium>(() =>
return new HorariumServer(jobRepository, settings);
});
```

In case of `HorariumServer`, don't forget to start it in your entypoint:

```csharp
((HorariumServer) container.GetInstance<IHorarium>()).Start();
```

## Failed repeat strategy for jobs

When a job fails, Horarium can handle this exception with the same strategy.
By default, the job repeats 10 times with delays of 10 minutes, 20 minutes, 30 minutes and etc.
You can override this strategy using `IFailedRepeatStrategy` interface.

Example of default `DefaultRepeatStrategy` implementation:

```csharp
public class DefaultRepeatStrategy :IFailedRepeatStrategy
{
public TimeSpan GetNextStartInterval(int countStarted)
{
const int increaseRepeat = 10;
return TimeSpan.FromMinutes(increaseRepeat * countStarted);
}
}
```

This class is called every time when a job fails, and it has to return `TimeSpan` of the next scheduled job run.
To override default behavior globally, change settings in ```HorariumSettings```

```csharp
new HorariumSettings
{
FailedRepeatStrategy = new CustomFailedRepeatStrategy(),
MaxRepeatCount = 7
});
```

To override the default behavior for a particular job:

```csharp
await horarium.Create<TestJob, int>(666)
.MaxRepeatCount(5)
.AddRepeatStrategy<DefaultRepeatStrategy>()
.Schedule();
```

If you want to disable all repeats, just set `MaxRepeatCount` to 1

```csharp
new HorariumSettings
{
MaxRepeatCount = 1
});
```
12 changes: 10 additions & 2 deletions src/Horarium.Mongo/JobMongoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ public JobDb ToJobDb()
NextJob = NextJob?.ToJobDb(),
Cron = Cron,
Delay = Delay,
ObsoleteInterval = ObsoleteInterval
ObsoleteInterval = ObsoleteInterval,
RepeatStrategy = RepeatStrategy,
MaxRepeatCount = MaxRepeatCount
};
}

Expand Down Expand Up @@ -61,6 +63,10 @@ public JobDb ToJobDb()

[BsonTimeSpanOptions(BsonType.Int64, TimeSpanUnits.Milliseconds)]
public TimeSpan ObsoleteInterval { get; set; }

public string RepeatStrategy { get; set; }

public int MaxRepeatCount { get; set; }

public static JobMongoModel CreateJobMongoModel(JobDb jobDb)
{
Expand All @@ -79,7 +85,9 @@ public static JobMongoModel CreateJobMongoModel(JobDb jobDb)
NextJob = jobDb.NextJob != null ? CreateJobMongoModel(jobDb.NextJob) : null,
Cron = jobDb.Cron,
Delay = jobDb.Delay,
ObsoleteInterval = jobDb.ObsoleteInterval
ObsoleteInterval = jobDb.ObsoleteInterval,
RepeatStrategy = jobDb.RepeatStrategy,
MaxRepeatCount = jobDb.MaxRepeatCount
};
}
}
Expand Down
41 changes: 41 additions & 0 deletions src/Horarium.Test/Builders/ParameterizedJobBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public async Task Schedule_NoPropertiesHaveBeenPassed_ShouldScheduleWithDefault(

// Assert
Assert.Equal(scheduledJob.StartAt, DateTime.UtcNow, TimeSpan.FromMilliseconds(500));
Assert.Null(scheduledJob.RepeatStrategy);
Assert.Equal(0, scheduledJob.MaxRepeatCount);
_jobsAdderMock.Verify(a => a.AddEnqueueJob(It.IsAny<JobMetadata>()), Times.Once);
_jobsAdderMock.VerifyNoOtherCalls();
}
Expand Down Expand Up @@ -102,5 +104,44 @@ await builder
_jobsAdderMock.Verify(a => a.AddEnqueueJob(It.IsAny<JobMetadata>()), Times.Once);
_jobsAdderMock.VerifyNoOtherCalls();
}

[Fact]
public async Task Schedule_SetFailedStrategy_SaveInJobMetadata()
{
// Arrange
var scheduledJob = new JobMetadata();
const int maxRepeatCount = 5;

var builder =
new ParameterizedJobBuilder<TestJob, string>(_jobsAdderMock.Object, "HALLO", _globalObsoleteInterval)
.AddRepeatStrategy<DefaultRepeatStrategy>()
.MaxRepeatCount(maxRepeatCount);

_jobsAdderMock.Setup(a => a.AddEnqueueJob(It.IsAny<JobMetadata>()))
.Returns(Task.CompletedTask)
.Callback((JobMetadata job) => scheduledJob = job);

// Act
await builder.Schedule();

// Assert
Assert.Equal(typeof(DefaultRepeatStrategy), scheduledJob.RepeatStrategy);
Assert.Equal(scheduledJob.MaxRepeatCount, maxRepeatCount);
_jobsAdderMock.Verify(a => a.AddEnqueueJob(It.IsAny<JobMetadata>()), Times.Once);
_jobsAdderMock.VerifyNoOtherCalls();
}

[Fact]
public async Task MaxRepeatCountIsZero_ThrowException()
{
// Arrange
const int maxRepeatCount = 0;

// Act
Assert.Throws<ArgumentOutOfRangeException>(() =>
new ParameterizedJobBuilder<TestJob, string>(_jobsAdderMock.Object, "HALLO", _globalObsoleteInterval)
.MaxRepeatCount(maxRepeatCount));

}
}
}
Loading

0 comments on commit 6044603

Please sign in to comment.