您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

109 行
3.2 KiB

using System;
using System.Collections;
using UnityEngine;
namespace Unity.Services.Relay.Helpers
{
internal static class AsyncOpRetry
{
public static AsyncOpRetry<T> FromCreateAsync<T>(Func<int, T> op)
{
return AsyncOpRetry<T>.FromCreateAsync(op);
}
}
internal class AsyncOpRetry<T>
{
private uint MaxRetries { get; set; } = 4;
private float JitterMagnitude { get; set; } = 1.0f;
private float DelayScale { get; set; } = 1.0f;
private float MaxDelayTime { get; set; } = 8.0f;
private Func<int, T> CreateOperation { get; set; }
private Func<T, bool> RetryCondition { get; set; }
private Action<T> OnComplete { get; set; }
private AsyncOpRetry(Func<int, T> createAsyncOp)
{
CreateOperation = createAsyncOp;
}
private static float AddJitter(float number, float magnitude)
{
return number + (UnityEngine.Random.value * magnitude);
}
private static float Pow2(float exponent, float scale)
{
return (float) (Math.Pow(2.0f, exponent) * scale);
}
private static float CalculateDelay(int attemptNumber, float maxDelayTime, float delayScale,
float jitterMagnitude)
{
float delayTime = Pow2(attemptNumber, delayScale);
delayTime = AddJitter(delayTime, jitterMagnitude);
delayTime = Math.Min(delayTime, maxDelayTime);
return delayTime;
}
public AsyncOpRetry<T> WithJitterMagnitude(float magnitude)
{
JitterMagnitude = Mathf.Clamp(magnitude, 0.001f, 1.0f);
return this;
}
public AsyncOpRetry<T> WithDelayScale(float scale)
{
DelayScale = Mathf.Clamp(scale, 0.05f, 1.0f);
return this;
}
public AsyncOpRetry<T> WithMaxDelayTime(float time)
{
MaxDelayTime = Mathf.Clamp(time, 0.1f, 60.0f);
return this;
}
public static AsyncOpRetry<T> FromCreateAsync(Func<int, T> op)
{
return new AsyncOpRetry<T>(op);
}
public AsyncOpRetry<T> WithRetryCondition(Func<T, bool> shouldRetry)
{
RetryCondition = shouldRetry;
return this;
}
public AsyncOpRetry<T> WhenComplete(Action<T> onComplete)
{
OnComplete = onComplete;
return this;
}
public AsyncOpRetry<T> UptoMaximumRetries(uint amount)
{
MaxRetries = amount;
return this;
}
public IEnumerator Run()
{
T asyncOp = default;
for (var attempt = 0; attempt <= MaxRetries; ++attempt)
{
asyncOp = CreateOperation(attempt + 1);
yield return asyncOp;
if ((!RetryCondition?.Invoke(asyncOp) ?? false))
{
break;
}
var delayTime = CalculateDelay(attempt, MaxDelayTime, DelayScale, JitterMagnitude);
yield return new WaitForSecondsRealtime(delayTime);
}
OnComplete?.Invoke(asyncOp);
}
}
}