Commit aa2e3340 authored by justcoding121's avatar justcoding121

retry fix

parent ab632d8e
......@@ -338,8 +338,7 @@ namespace Titanium.Web.Proxy
}
finally
{
if (!calledRequestHandler
&& prefetchConnectionTask != null)
if (!calledRequestHandler)
{
await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
}
......
......@@ -11,66 +11,73 @@ namespace Titanium.Web.Proxy.Network
private readonly int retries;
private readonly TcpConnectionFactory tcpConnectionFactory;
private TcpServerConnection currentConnection;
private Exception exception;
internal RetryPolicy(int retries, TcpConnectionFactory tcpConnectionFactory)
{
this.retries = retries;
this.tcpConnectionFactory = tcpConnectionFactory;
}
//get the policy
private Policy getRetryPolicy()
{
return Policy.Handle<T>()
.RetryAsync(retries,
onRetryAsync: async (ex, i, context) =>
{
if (context["connection"] != null)
{
//close connection on error
var connection = (TcpServerConnection)context["connection"];
await tcpConnectionFactory.Release(connection, true);
context["connection"] = null;
}
});
}
/// <summary>
/// Execute and retry the given action until retry number of times.
/// </summary>
/// <param name="action">The action to retry.</param>
/// <param name="generator">The Tcp connection generator to be invoked to get new connection for retry.</param>
/// <param name="initialConnection">Initial Tcp connection to use.</param>
/// <returns></returns>
internal Task ExecuteAsync(Func<TcpServerConnection, Task> action,
Func<Task<TcpServerConnection>> generator, ref TcpServerConnection initialConnection)
/// <returns>Returns the latest connection used and the latest exception if any.</returns>
internal async Task<RetryResult> ExecuteAsync(Func<TcpServerConnection, Task> action,
Func<Task<TcpServerConnection>> generator, TcpServerConnection initialConnection)
{
var outerContext = new Dictionary<string, object> { { "connection", initialConnection } };
Task result;
currentConnection = initialConnection;
try
{
result = getRetryPolicy().ExecuteAsync(async (context) =>
//retry on error with polly policy
//do not use polly context to store connection; it does not save states b/w attempts
await getRetryPolicy().ExecuteAsync(async () =>
{
//setup connection
var connection = context["connection"] as TcpServerConnection ??
currentConnection = currentConnection as TcpServerConnection ??
await generator();
//try
await action(currentConnection);
context["connection"] = connection;
//retry
await action(connection);
});
}
catch (Exception e) { exception = e; }
}, outerContext);
return new RetryResult(currentConnection, exception);
}
//all retries failed
finally
//get the policy
private Policy getRetryPolicy()
{
return Policy.Handle<T>()
.RetryAsync(retries,
onRetryAsync: async (ex, i, context) =>
{
if (currentConnection != null)
{
//update the original connection to last used connection
initialConnection = outerContext["connection"] as TcpServerConnection;
//close connection on error
await tcpConnectionFactory.Release(currentConnection, true);
currentConnection = null;
}
});
}
}
internal class RetryResult
{
internal bool IsSuccess => Exception == null;
internal TcpServerConnection LatestConnection { get; }
internal Exception Exception { get; }
return result;
internal RetryResult(TcpServerConnection lastConnection, Exception exception)
{
LatestConnection = lastConnection;
Exception = exception;
}
}
}
......@@ -211,7 +211,7 @@ namespace Titanium.Web.Proxy
noCache: false, cancellationToken: cancellationToken);
//for connection pool, retry fails until cache is exhausted.
await retryPolicy<ServerConnectionException>().ExecuteAsync(async (serverConnection) =>
var result = await retryPolicy<ServerConnectionException>().ExecuteAsync(async (serverConnection) =>
{
// if upgrading to websocket then relay the request without reading the contents
if (request.UpgradeToWebSocket)
......@@ -226,7 +226,16 @@ namespace Titanium.Web.Proxy
// construct the web request that we are going to issue on behalf of the client.
await handleHttpSessionRequestInternal(serverConnection, args);
}, generator, ref connection);
}, generator, connection);
//update connection to latest used
connection = result.LatestConnection;
//throw if exception happened
if(!result.IsSuccess)
{
throw result.Exception;
}
//user requested
if (args.WebSession.CloseServerConnection)
......
......@@ -164,8 +164,7 @@ namespace Titanium.Web.Proxy
}
finally
{
if (!calledRequestHandler
&& prefetchConnectionTask != null)
if (!calledRequestHandler)
{
await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment