Skip to content

Commit

Permalink
Run ConfiguredTaskAwaitable callback as Task
Browse files Browse the repository at this point in the history
  • Loading branch information
neon-nyan committed Feb 1, 2025
1 parent 72084d9 commit ee32899
Showing 1 changed file with 15 additions and 53 deletions.
68 changes: 15 additions & 53 deletions CollapseLauncher/Classes/Extension/TaskExtensions.TaskAwaitable.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Hi3Helper;
using System;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -27,61 +26,24 @@ internal static async Task<TResult?>
int? retryAttempt = null,
ActionOnTimeOutRetry? actionOnRetry = null,
CancellationToken fromToken = default)
=> await WaitForRetryAsync(funcCallback.AsTaskCallback(fromToken),
timeout,
timeoutStep,
retryAttempt,
actionOnRetry,
fromToken);

internal static ActionTimeoutTaskCallback<TResult?> AsTaskCallback<TResult>(this Func<ActionTimeoutTaskAwaitableCallback<TResult?>> func,
CancellationToken fromToken)
{
timeout ??= DefaultTimeoutSec;
timeoutStep ??= 0;
retryAttempt ??= DefaultRetryAttempt;
return ActionTimeoutCallback;

int retryAttemptCurrent = 1;
Exception? lastException = null;
while (retryAttemptCurrent < retryAttempt)
async Task<TResult?> ActionTimeoutCallback(CancellationToken innerToken)
{
fromToken.ThrowIfCancellationRequested();
CancellationTokenSource? innerCancellationToken = null;
CancellationTokenSource? consolidatedToken = null;

try
{
innerCancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(timeout ?? DefaultTimeoutSec));
consolidatedToken = CancellationTokenSource.CreateLinkedTokenSource(innerCancellationToken.Token, fromToken);

ActionTimeoutTaskAwaitableCallback<TResult?> delegateCallback = funcCallback();
return await delegateCallback(consolidatedToken.Token);
}
catch (OperationCanceledException) when (fromToken.IsCancellationRequested) { throw; }
catch (Exception ex)
{
lastException = ex;
actionOnRetry?.Invoke(retryAttemptCurrent, (int)retryAttempt, timeout ?? 0, timeoutStep ?? 0);

if (ex is TimeoutException)
{
string msg = $"The operation has timed out! Retrying attempt left: {retryAttemptCurrent}/{retryAttempt}";
Logger.LogWriteLine(msg, LogType.Warning, true);
}
else
{
string msg = $"The operation has thrown an exception! Retrying attempt left: {retryAttemptCurrent}/{retryAttempt}\r\n{ex}";
Logger.LogWriteLine(msg, LogType.Error, true);
}

retryAttemptCurrent++;
timeout += timeoutStep;
}
finally
{
innerCancellationToken?.Dispose();
consolidatedToken?.Dispose();
}
ActionTimeoutTaskAwaitableCallback<TResult?> callback = func.Invoke();
ConfiguredTaskAwaitable<TResult?> callbackAwaitable = callback.Invoke(fromToken);
return await callbackAwaitable;
}

if (lastException is not null
&& !fromToken.IsCancellationRequested)
throw lastException is TaskCanceledException ?
new TimeoutException("The operation has timed out with inner exception!", lastException) :
lastException;

throw new TimeoutException("The operation has timed out!");
}
}
}

0 comments on commit ee32899

Please sign in to comment.