Commit f3d0c693 authored by Nick Craver's avatar Nick Craver

Sentinel: don't use async over sync with .Result

parent b56e707a
...@@ -2303,53 +2303,16 @@ internal void OnManagedConnectionFailed(object sender, ConnectionFailedEventArgs ...@@ -2303,53 +2303,16 @@ internal void OnManagedConnectionFailed(object sender, ConnectionFailedEventArgs
{ {
SwitchMaster(e.EndPoint, connection); SwitchMaster(e.EndPoint, connection);
}, null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1)); }, null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1));
//connection.sentinelMasterReconnectTimer.AutoReset = true;
//connection.sentinelMasterReconnectTimer.Start();
} }
} }
internal EndPoint GetConfiguredMasterForService(string serviceName, int timeoutmillis = -1) internal EndPoint GetConfiguredMasterForService(string serviceName) =>
{ GetServerSnapshot()
Task<EndPoint>[] sentinelMasters = GetServerSnapshot().ToArray() .ToArray()
.Where(s => s.ServerType == ServerType.Sentinel) .Where(s => s.ServerType == ServerType.Sentinel)
.Select(s => GetServer(s.EndPoint).SentinelGetMasterAddressByNameAsync(serviceName)) .AsParallel()
.ToArray(); .Select(s => GetServer(s.EndPoint).SentinelGetMasterAddressByName(serviceName))
.First(r => r != null);
Task<Task<EndPoint>> firstCompleteRequest = WaitFirstNonNullIgnoreErrorsAsync(sentinelMasters);
if (!firstCompleteRequest.Wait(timeoutmillis))
throw new TimeoutException("Timeout resolving master for service");
if (firstCompleteRequest.Result.Result == null)
throw new Exception("Unable to determine master");
return firstCompleteRequest.Result.Result;
}
private static async Task<Task<T>> WaitFirstNonNullIgnoreErrorsAsync<T>(Task<T>[] tasks)
{
if (tasks == null) throw new ArgumentNullException("tasks");
if (tasks.Length == 0) return null;
var typeNullable = (Nullable.GetUnderlyingType(typeof(T)) != null);
var taskList = tasks.Cast<Task>().ToList();
try
{
while (taskList.Count > 0)
{
var allTasksAwaitingAny = Task.WhenAny(taskList).ObserveErrors();
var result = await allTasksAwaitingAny.ForAwait();
taskList.Remove((Task<T>)result);
if (((Task<T>)result).IsFaulted) continue;
if ((!typeNullable) || ((Task<T>)result).Result != null)
return (Task<T>)result;
}
}
catch
{ }
return null;
}
internal EndPoint currentSentinelMasterEndPoint; internal EndPoint currentSentinelMasterEndPoint;
...@@ -2419,26 +2382,22 @@ private T Retry<T>(int times, int interval, Func<T> func, string message) ...@@ -2419,26 +2382,22 @@ private T Retry<T>(int times, int interval, Func<T> func, string message)
throw new NullReferenceException(message); throw new NullReferenceException(message);
} }
internal void UpdateSentinelAddressList(string serviceName, int timeoutmillis = 500) internal void UpdateSentinelAddressList(string serviceName)
{ {
Task<EndPoint[]>[] sentinels = GetServerSnapshot().ToArray() var firstCompleteRequest = GetServerSnapshot()
.Where(s => s.ServerType == ServerType.Sentinel) .ToArray()
.Select(s => GetServer(s.EndPoint).SentinelGetSentinelAddressesAsync(serviceName)) .Where(s => s.ServerType == ServerType.Sentinel)
.ToArray(); .AsParallel()
.Select(s => GetServer(s.EndPoint).SentinelGetSentinelAddresses(serviceName))
Task<Task<EndPoint[]>> firstCompleteRequest = WaitFirstNonNullIgnoreErrorsAsync(sentinels); .First(r => r != null);
// Ignore errors, as having an updated sentinel list is // Ignore errors, as having an updated sentinel list is
// not essential // not essential
if (firstCompleteRequest.Result?.Result == null) if (firstCompleteRequest == null)
return;
if (!firstCompleteRequest.Wait(timeoutmillis))
return;
if (firstCompleteRequest.Result.Result == null)
return; return;
bool hasNew = false; bool hasNew = false;
foreach (EndPoint newSentinel in firstCompleteRequest.Result.Result.Where(x => !RawConfig.EndPoints.Contains(x))) foreach (EndPoint newSentinel in firstCompleteRequest.Where(x => !RawConfig.EndPoints.Contains(x)))
{ {
hasNew = true; hasNew = true;
RawConfig.EndPoints.Add(newSentinel); RawConfig.EndPoints.Add(newSentinel);
......
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