public void RetryPolicy_ExponentialEaseIn_ShouldBeCorrect() { // fail on all retries var startTime = DateTime.Now; var timeBetweenRetries = TimeSpan.FromMilliseconds(50); var maxTimeBetweenRetries = TimeSpan.FromMilliseconds(500); var maxRetries = 10; var retryTimes = new List <TimeSpan>(); var retryPolicy = RetryPolicyFactory.Create(RetryPolicy.EasedBackoff, new RetryPolicyOptions { EasingFunction = AnyRetry.Math.EasingFunction.ExponentialEaseOut, MaxRetryInterval = maxTimeBetweenRetries }); for (var i = 0; i < maxRetries; i++) { retryTimes.Add(retryPolicy.ApplyPolicy(RetryParameters.Create(startTime, timeBetweenRetries, i, maxRetries))); } // elastic ease in var toleranceSeconds = 0.001; Assert.That(retryTimes.Skip(0).First().TotalSeconds, Is.EqualTo(0.05).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(1).First().TotalSeconds, Is.EqualTo(0.3185313).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(2).First().TotalSeconds, Is.EqualTo(0.4428445).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(3).First().TotalSeconds, Is.EqualTo(0.5).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(4).First().TotalSeconds, Is.EqualTo(0.5).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(5).First().TotalSeconds, Is.EqualTo(0.5).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(6).First().TotalSeconds, Is.EqualTo(0.5).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(7).First().TotalSeconds, Is.EqualTo(0.5).Within(toleranceSeconds)); // last timeout should be equal to max Assert.AreEqual(retryTimes.Skip(9).First(), TimeSpan.FromMilliseconds(500)); }
public Guid AddJob <TJob>(Expression <Action <TJob> > jobExpression, RetryParameters retryParameters = null, DateTimeOffset?executionTime = null, string queueName = "default") { var jobInfo = JobCreator.Create <TJob>(jobExpression); var newJob = new OddJobWithMetaAndStorageData() { JobId = Guid.NewGuid(), JobArgs = jobInfo.JobArgs, MethodName = jobInfo.MethodName, RetryParameters = retryParameters, TypeExecutedOn = jobInfo.TypeExecutedOn, CreatedOn = DateTime.Now, Status = JobStates.New }; if (jobStore.ContainsKey(queueName) == false) { lock (dictionaryLock) { jobStore.GetOrAdd(queueName, new List <OddJobWithMetaAndStorageData>()); } } lock (jobLock) { jobStore[queueName].Add(newJob); } return(newJob.JobId); }
/// <summary> /// Creates a Serialized Job Definition. /// Complex Parameters are stored as JSON strings, /// And Type Information is stored in a nonversioned format by default. /// </summary> /// <typeparam name="T">The type of the job to execute.</typeparam> /// <param name="jobExpression">The job Expression</param> /// <param name="retryParameters">The retry parameters to use, if any.</param> /// <param name="executionTime">A time to schedule; use this to schedule jobs in future</param> /// <param name="queueName">The Queue to resolve</param> /// <param name="typeNameSerializer">To change the default behavior (nonversioned types) specify a different <see cref="ITypeNameSerializer"/> here.</param> /// <returns>A wire-safe Serializable job definition.</returns> public static SerializableOddJob CreateJobDefinition <T>(Expression <Action <T> > jobExpression, RetryParameters retryParameters = null, DateTimeOffset?executionTime = null, string queueName = "default", ITypeNameSerializer typeNameSerializer = null) { var job = JobCreator.Create(jobExpression); var mySer = typeNameSerializer ?? new UnversionedTypeSerializer(); return(new SerializableOddJob() { JobId = job.JobId, MethodName = job.MethodName, JobArgs = job.JobArgs.Select((a, i) => new OddJobSerializedParameter() { Ordinal = i, Name = a.Name, Value = Newtonsoft.Json.JsonConvert.SerializeObject(a.Value), TypeName = mySer.GetTypeName(a.Value.GetType()) }).ToArray(), TypeExecutedOn = mySer.GetTypeName(job.TypeExecutedOn), Status = job.Status, MethodGenericTypes = job.MethodGenericTypes.Select(q => mySer.GetTypeName(q)).ToArray(), RetryParameters = retryParameters ?? new RetryParameters(), ExecutionTime = executionTime, QueueName = queueName }); }
public void RetryPolicy_Exponential_ShouldBeCorrect() { // fail on all retries var startTime = DateTime.Now; var timeBetweenRetries = TimeSpan.FromMilliseconds(50); var maxTimeBetweenRetries = TimeSpan.FromMilliseconds(10000); var maxRetries = 10; var retryTimes = new List <TimeSpan>(); var options = new RetryPolicyOptions { MaxRetryInterval = maxTimeBetweenRetries, }; var retryPolicy = RetryPolicyFactory.Create(RetryPolicy.ExponentialBackoff, options); for (var i = 0; i < maxRetries; i++) { retryTimes.Add(retryPolicy.ApplyPolicy(RetryParameters.Create(startTime, timeBetweenRetries, i, maxRetries))); } // there is a 20% randomness to the delay var randomDelay = TimeSpan.FromMilliseconds(timeBetweenRetries.Milliseconds * 0.2); // first timeout should have nearly no delay Assert.LessOrEqual(timeBetweenRetries - randomDelay, retryTimes.First()); // exponential increase Assert.LessOrEqual(TimeSpan.FromMilliseconds(timeBetweenRetries.TotalMilliseconds * 2 - (timeBetweenRetries.TotalMilliseconds * 2 * 0.2)), retryTimes.Skip(1).First()); Assert.LessOrEqual(TimeSpan.FromMilliseconds(timeBetweenRetries.TotalMilliseconds * 4 - (timeBetweenRetries.TotalMilliseconds * 4 * 0.2)), retryTimes.Skip(2).First()); Assert.LessOrEqual(TimeSpan.FromMilliseconds(timeBetweenRetries.TotalMilliseconds * 8 - (timeBetweenRetries.TotalMilliseconds * 8 * 0.2)), retryTimes.Skip(3).First()); Assert.LessOrEqual(TimeSpan.FromMilliseconds(timeBetweenRetries.TotalMilliseconds * 16 - (timeBetweenRetries.TotalMilliseconds * 16 * 0.2)), retryTimes.Skip(4).First()); Assert.LessOrEqual(TimeSpan.FromMilliseconds(timeBetweenRetries.TotalMilliseconds * 32 - (timeBetweenRetries.TotalMilliseconds * 32 * 0.2)), retryTimes.Skip(5).First()); Assert.LessOrEqual(TimeSpan.FromMilliseconds(timeBetweenRetries.TotalMilliseconds * 64 - (timeBetweenRetries.TotalMilliseconds * 64 * 0.2)), retryTimes.Skip(6).First()); Assert.LessOrEqual(TimeSpan.FromMilliseconds(timeBetweenRetries.TotalMilliseconds * 128 - (timeBetweenRetries.TotalMilliseconds * 128 * 0.2)), retryTimes.Skip(7).First()); Assert.AreEqual(TimeSpan.FromMilliseconds(10000), retryTimes.Skip(8).First()); Assert.AreEqual(TimeSpan.FromMilliseconds(10000), retryTimes.Skip(9).First()); }
public virtual Guid AddJob <TJob>(Expression <Action <TJob> > jobExpression, RetryParameters retryParameters = null, DateTimeOffset?executionTime = null, string queueName = "default") { using (var conn = _jobQueueConnectionFactory.CreateDataConnection(_mappingSchema.MappingSchema)) { var ser = SerializableJobCreator.CreateJobDefinition(jobExpression, retryParameters, executionTime, queueName); AddJob(ser); return(ser.JobId); } }
/// <summary> /// Apply the policy /// </summary> /// <param name="retryParameters"></param> /// <returns></returns> public TimeSpan ApplyPolicy(RetryParameters retryParameters) { var retrySteps = _options.MaxRetrySteps ?? retryParameters.RetryIteration; var retryCount = _options.MaxRetrySteps ?? retryParameters.RetryCount; var maxInterval = _options.MaxRetryInterval; if (maxInterval == TimeSpan.MinValue) { maxInterval = TimeSpan.FromMilliseconds(retryParameters.RetryInterval.TotalMilliseconds * retrySteps); } var minInterval = retryParameters.RetryInterval; return(GetRetryTimeoutSeconds(retryParameters.RetryIteration, retryCount, minInterval, maxInterval, _options.EasingFunction)); }
public Guid AddJob <TJob>(Expression <Action <TJob> > jobExpression, RetryParameters retryParameters = null, DateTimeOffset?executionTime = null, string queueName = "default") { var jobData = JobCreator.Create(jobExpression); var toSer = new FileSystemJobMetaData() { JobId = Guid.NewGuid(), JobArgs = jobData.JobArgs, MethodName = jobData.MethodName, RetryParameters = retryParameters ?? new RetryParameters(0, TimeSpan.FromSeconds(0), 0, null), TypeExecutedOn = jobData.TypeExecutedOn, QueueName = queueName, CreatedOn = DateTime.Now, Status = JobStates.New, MethodGenericTypes = jobData.MethodGenericTypes }; WriteJobToQueue(toSer); return(toSer.JobId); }
public void RetryPolicy_SineEaseIn_WithSteps_ShouldBeCorrect() { // fail on all retries const int maxRetrySteps = 5; const int maxRetries = 30; var startTime = DateTime.Now; var timeBetweenRetries = TimeSpan.FromMilliseconds(500); var maxTimeBetweenRetries = TimeSpan.FromMilliseconds(2000); var retryTimes = new List <TimeSpan>(); var options = new RetryPolicyOptions { EasingFunction = AnyRetry.Math.EasingFunction.SineEaseIn, MaxRetryInterval = maxTimeBetweenRetries, MaxRetrySteps = maxRetrySteps }; var retryPolicy = RetryPolicyFactory.Create(RetryPolicy.EasedBackoff, options); for (var i = 0; i < maxRetries; i++) { retryTimes.Add(retryPolicy.ApplyPolicy(RetryParameters.Create(startTime, timeBetweenRetries, i, maxRetries))); } // linear increase up to a max of maxRetrySteps then it should level off Assert.AreEqual(0.5, System.Math.Round(retryTimes.Skip(0).First().TotalSeconds, 2)); Assert.AreEqual(0.6522409, retryTimes.Skip(1).First().TotalSeconds); Assert.AreEqual(1.0857864, retryTimes.Skip(2).First().TotalSeconds); Assert.AreEqual(1.7346331, retryTimes.Skip(3).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(4).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(5).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(6).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(7).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(8).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(10).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(11).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(12).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(13).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(14).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(15).First().TotalSeconds); Assert.AreEqual(2.0, retryTimes.Skip(16).First().TotalSeconds); }
public void RetryPolicy_EasedLinear_WithSteps_ShouldBeCorrect() { // fail on all retries const int maxRetrySteps = 5; const int maxRetries = 10; var startTime = DateTime.Now; var timeBetweenRetries = TimeSpan.FromMilliseconds(500); var maxTimeBetweenRetries = TimeSpan.FromMilliseconds(10000); var retryTimes = new List <TimeSpan>(); var options = new RetryPolicyOptions { EasingFunction = AnyRetry.Math.EasingFunction.Linear, MaxRetryInterval = maxTimeBetweenRetries, MaxRetrySteps = maxRetrySteps }; var retryPolicy = RetryPolicyFactory.Create(RetryPolicy.EasedBackoff, options); for (var i = 0; i < maxRetries; i++) { retryTimes.Add(retryPolicy.ApplyPolicy(RetryParameters.Create(startTime, timeBetweenRetries, i, maxRetries))); } // linear increase up to a max of maxRetrySteps then it should level off var toleranceSeconds = 0.0; Assert.That(retryTimes.Skip(0).First().TotalSeconds, Is.EqualTo(0.5).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(1).First().TotalSeconds, Is.EqualTo(3.0).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(2).First().TotalSeconds, Is.EqualTo(5.5).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(3).First().TotalSeconds, Is.EqualTo(8.0).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(4).First().TotalSeconds, Is.EqualTo(10.0).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(5).First().TotalSeconds, Is.EqualTo(10.0).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(6).First().TotalSeconds, Is.EqualTo(10.0).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(7).First().TotalSeconds, Is.EqualTo(10.0).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(8).First().TotalSeconds, Is.EqualTo(10.0).Within(toleranceSeconds)); Assert.That(retryTimes.Skip(9).First().TotalSeconds, Is.EqualTo(10.0).Within(toleranceSeconds)); }
/// <summary> /// Apply the policy /// </summary> /// <param name="retryParameters"></param> /// <returns></returns> public TimeSpan ApplyPolicy(RetryParameters retryParameters) { return(retryParameters.RetryInterval); }
/// <summary> /// Apply the retry policy /// </summary> /// <param name="retryParameters"></param> /// <returns></returns> public TimeSpan ApplyPolicy(RetryParameters retryParameters) { return(SleepIntervalMs(retryParameters.RetryInterval, retryParameters.RetryIteration, _defaultMaxRelativeRandomSpreadPercent)); }