From cd7700265ac18bddeffac03c5f5e5e11733fa3e1 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Thu, 5 Apr 2018 16:56:19 +1100 Subject: [PATCH] Backend/Ether: workaround shitty HttpRequestException API The underneath status code of this exception[3] is tricky to catch (see its shitty API and Microsoft's unwillingness to fix this mess here[1]) as it comes just inside the exception message (plus to add insult to injury, CloudFlare has invented their own[2] codes). [1] https://github.com/dotnet/corefx/issues/24253 [2] https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#Cloudflare [3] [ERROR] FATAL UNHANDLED EXCEPTION: System.AggregateException: One or more errors occurred. ---> System.Exception: Some problem when connecting to https://etc-parity.callisto.network ---> System.AggregateException: One or more errors occurred. ---> Nethereum.JsonRpc.Client.RpcClientUnknownException: Error occurred when trying to send rpc requests(s) ---> System.Net.Http.HttpRequestException: 522 (Origin Connection Time-out) at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode () [0x0002a] in <9f3d2d95936b4d78aa542c9f32650f41>:0 at Nethereum.JsonRpc.Client.RpcClient+d__17.MoveNext () [0x0012a] in <637b104e55b941dcb1efbb91e63ee797>:0 --- End of inner exception stack trace --- at Nethereum.JsonRpc.Client.RpcClient+d__17.MoveNext () [0x00286] in <637b104e55b941dcb1efbb91e63ee797>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in :0 at Nethereum.JsonRpc.Client.RpcClient+d__12`1[T].MoveNext () [0x000a2] in <637b104e55b941dcb1efbb91e63ee797>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in :0 at Nethereum.JsonRpc.Client.ClientBase+d__4`1[T].MoveNext () [0x0014f] in <5b4585c1c99947d78244d74142f50fce>:0 --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in :0 at System.Threading.Tasks.Task.Wait (System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) [0x00043] in :0 at System.Threading.Tasks.Task.Wait (System.TimeSpan timeout) [0x00022] in :0 at GWallet.Backend.Ether.Server.WaitOnTask[T,R] (Microsoft.FSharp.Core.FSharpFunc`2[T,TResult] func, T arg) [0x0003d] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at GWallet.Backend.Ether.Server+web3Func@130-2.Invoke (Nethereum.Web3.Web3 web3, System.String publicAddress) [0x00013] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at Microsoft.FSharp.Core.OptimizedClosures+Invoke@3253[T2,TResult,T1].Invoke (T2 u) [0x00001] in <59964427904cf4daa745038327449659>:0 at GWallet.Backend.Ether.Server+GetUnconfirmedEtherBalance@133-2.Invoke (System.String arg10) [0x00001] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at Microsoft.FSharp.Core.FSharpFunc`2[T,TResult].InvokeFast[V] (Microsoft.FSharp.Core.FSharpFunc`2[T,TResult] func, T arg1, TResult arg2) [0x0001f] in <59964427904cf4daa745038327449659>:0 at GWallet.Backend.Ether.Server+serverFuncs@101[T,R].Invoke (GWallet.Backend.Ether.Server+SomeWeb3 web3, T arg) [0x00002] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 --- End of inner exception stack trace --- at .$FaultTolerantParallelClient+asyncJobsToRunInParallelAsAsync@134-3[E,R].Invoke (System.Exception _arg1) [0x000a9] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at Microsoft.FSharp.Control.AsyncBuilderImpl+tryWithExnA@881[a].Invoke (System.Runtime.ExceptionServices.ExceptionDispatchInfo edi) [0x0000d] in <59964427904cf4daa745038327449659>:0 at Microsoft.FSharp.Control.AsyncBuilderImpl+callA@839[b,a].Invoke (Microsoft.FSharp.Control.AsyncParams`1[T] args) [0x00052] in <59964427904cf4daa745038327449659>:0 --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in :0 at System.Threading.Tasks.Task`1[TResult].GetResultCore (System.Boolean waitCompletionNotification) [0x0002b] in :0 at System.Threading.Tasks.Task`1[TResult].get_Result () [0x0000f] in :0 at GWallet.Backend.FaultTolerantParallelClient`1[E].WhenSomeInternal[T,R] (System.Int32 numberOfResultsRequired, Microsoft.FSharp.Collections.FSharpList`1[T] tasks, Microsoft.FSharp.Collections.FSharpList`1[T] resultsSoFar, Microsoft.FSharp.Collections.FSharpList`1[T] failedFuncsSoFar) [0x0009a] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at GWallet.Backend.FaultTolerantParallelClient`1[E].WhenSome[T,R] (System.Int32 numberOfConsistentResultsRequired, System.Collections.Generic.IEnumerable`1[T] jobs, Microsoft.FSharp.Collections.FSharpList`1[T] resultsSoFar, Microsoft.FSharp.Collections.FSharpList`1[T] failedFuncsSoFar) [0x00012] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at GWallet.Backend.FaultTolerantParallelClient`1[E].QueryInternal[T,R] (T args, Microsoft.FSharp.Collections.FSharpList`1[T] funcs, Microsoft.FSharp.Collections.FSharpList`1[T] resultsSoFar, Microsoft.FSharp.Collections.FSharpList`1[T] failedFuncsSoFar, System.UInt16 retries) [0x001cf] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at .$FaultTolerantParallelClient+Query@165[R,E,T].Invoke (Microsoft.FSharp.Core.Unit unitVar) [0x00023] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at Microsoft.FSharp.Control.AsyncBuilderImpl+callA@839[b,a].Invoke (Microsoft.FSharp.Control.AsyncParams`1[T] args) [0x00052] in <59964427904cf4daa745038327449659>:0 --- End of stack trace from previous location where exception was thrown --- at GWallet.Backend.Infrastructure.Report[a] (System.Exception ex) [0x0000c] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at GWallet.Backend.Infrastructure.OnUnhandledException[a] (System.Object sender, System.UnhandledExceptionEventArgs args) [0x00007] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at GWallet.Backend.Infrastructure+SetupSentryHook@28-4.Invoke (System.Object sender, System.UnhandledExceptionEventArgs e) [0x00001] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 ---> (Inner Exception #0) System.Exception: Some problem when connecting to https://etc-parity.callisto.network ---> System.AggregateException: One or more errors occurred. ---> Nethereum.JsonRpc.Client.RpcClientUnknownException: Error occurred when trying to send rpc requests(s) ---> System.Net.Http.HttpRequestException: 522 (Origin Connection Time-out) at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode () [0x0002a] in <9f3d2d95936b4d78aa542c9f32650f41>:0 at Nethereum.JsonRpc.Client.RpcClient+d__17.MoveNext () [0x0012a] in <637b104e55b941dcb1efbb91e63ee797>:0 --- End of inner exception stack trace --- at Nethereum.JsonRpc.Client.RpcClient+d__17.MoveNext () [0x00286] in <637b104e55b941dcb1efbb91e63ee797>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in :0 at Nethereum.JsonRpc.Client.RpcClient+d__12`1[T].MoveNext () [0x000a2] in <637b104e55b941dcb1efbb91e63ee797>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in :0 at Nethereum.JsonRpc.Client.ClientBase+d__4`1[T].MoveNext () [0x0014f] in <5b4585c1c99947d78244d74142f50fce>:0 --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in :0 at System.Threading.Tasks.Task.Wait (System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) [0x00043] in :0 at System.Threading.Tasks.Task.Wait (System.TimeSpan timeout) [0x00022] in :0 at GWallet.Backend.Ether.Server.WaitOnTask[T,R] (Microsoft.FSharp.Core.FSharpFunc`2[T,TResult] func, T arg) [0x0003d] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at GWallet.Backend.Ether.Server+web3Func@130-2.Invoke (Nethereum.Web3.Web3 web3, System.String publicAddress) [0x00013] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at Microsoft.FSharp.Core.OptimizedClosures+Invoke@3253[T2,TResult,T1].Invoke (T2 u) [0x00001] in <59964427904cf4daa745038327449659>:0 at GWallet.Backend.Ether.Server+GetUnconfirmedEtherBalance@133-2.Invoke (System.String arg10) [0x00001] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at Microsoft.FSharp.Core.FSharpFunc`2[T,TResult].InvokeFast[V] (Microsoft.FSharp.Core.FSharpFunc`2[T,TResult] func, T arg1, TResult arg2) [0x0001f] in <59964427904cf4daa745038327449659>:0 at GWallet.Backend.Ether.Server+serverFuncs@101[T,R].Invoke (GWallet.Backend.Ether.Server+SomeWeb3 web3, T arg) [0x00002] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 --- End of inner exception stack trace --- at .$FaultTolerantParallelClient+asyncJobsToRunInParallelAsAsync@134-3[E,R].Invoke (System.Exception _arg1) [0x000a9] in <5ac5b2d75952d4f0a7450383d7b2c55a>:0 at Microsoft.FSharp.Control.AsyncBuilderImpl+tryWithExnA@881[a].Invoke (System.Runtime.ExceptionServices.ExceptionDispatchInfo edi) [0x0000d] in <59964427904cf4daa745038327449659>:0 at Microsoft.FSharp.Control.AsyncBuilderImpl+callA@839[b,a].Invoke (Microsoft.FSharp.Control.AsyncParams`1[T] args) [0x00052] in <59964427904cf4daa745038327449659>:0 <--- --- src/GWallet.Backend/Ether/EtherServer.fs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/GWallet.Backend/Ether/EtherServer.fs b/src/GWallet.Backend/Ether/EtherServer.fs index 362a9d643..721eddf09 100644 --- a/src/GWallet.Backend/Ether/EtherServer.fs +++ b/src/GWallet.Backend/Ether/EtherServer.fs @@ -26,12 +26,19 @@ module Server = new(message: string, innerException: Exception) = { inherit Exception(message, innerException) } new(message: string) = { inherit Exception(message) } - type ServerTimedOutException(message:string) = - inherit ConnectionUnsuccessfulException (message) + type ServerTimedOutException = + inherit ConnectionUnsuccessfulException + + new(message: string, innerException: Exception) = { inherit ConnectionUnsuccessfulException(message, innerException) } + new(message: string) = { inherit ConnectionUnsuccessfulException(message) } type ServerCannotBeResolvedException(message:string, innerException: Exception) = inherit ConnectionUnsuccessfulException (message, innerException) + type CloudFlareError = + | ConnectionTimeOut = 522 + | WebServerDown = 521 + //let private PUBLIC_WEB3_API_ETH_INFURA = "https://mainnet.infura.io:8545" ? let private ethWeb3Infura = SomeWeb3("https://mainnet.infura.io/mew") let private ethWeb3Mew = SomeWeb3("https://api.myetherapi.com/eth") // docs: https://www.myetherapi.com/ @@ -69,7 +76,14 @@ module Server = | ex -> let maybeWebEx = FSharpUtil.FindException ex match maybeWebEx with - | None -> reraise() + | None -> + let maybeHttpReqEx = FSharpUtil.FindException ex + match maybeHttpReqEx with + | None -> reraise() + | Some(httpReqEx) -> + if (httpReqEx.Message.StartsWith(sprintf "%d " (int CloudFlareError.ConnectionTimeOut))) then + raise (ServerTimedOutException(exMsg, httpReqEx)) + reraise() | Some(webEx) -> if (webEx.Status = WebExceptionStatus.NameResolutionFailure) then raise (ServerCannotBeResolvedException(exMsg, webEx))