将 Polly HTTP 请求转换为 F#
Translate Polly HTTP request to F#
我正在使用 Polly 发出 HTTP 请求。我想在数组中的每个代理上等待 1 秒后重试一次。
我怎样才能做得更好?
我如何在 F# 中执行此操作?
public static Result RequestWithRetry(string url, string[] proxies, string username, string password)
{
if (proxies == null) throw new ArgumentNullException("null proxies array");
var client = new WebClient { Credentials = new NetworkCredential(username, password) };
var result = String.Empty;
var proxyIndex = 0;
var policy = Policy
.Handle<Exception>()
.WaitAndRetry(new[]
{
TimeSpan.FromSeconds(1)
}, (exception, timeSpan) => proxyIndex++);
policy.Execute(() =>
{
if (proxyIndex >= proxies?.Length) throw new Exception($"Exhausted proxies: {String.Join(", ", proxies)}");
client.Proxy = new WebProxy(proxies?[proxyIndex]) { UseDefaultCredentials = true };
result = client.DownloadString(new Uri(url));
});
return new Result(value: result, proxy: proxies[proxyIndex]);
}
我能够将这个翻译整合在一起。我不太喜欢它,尽管我确实在这个过程中学到了很多关于 F# 和 Action
的知识。
type Result = { Value: string; Proxy: string }
let request (proxies:string[]) (username:string) (password:string) (url:string) : Result =
if (proxies = null) then raise <| new ArgumentNullException()
use client = new WebClient()
client.Credentials <- NetworkCredential(username, password)
let mutable result = String.Empty;
let mutable proxyIndex = 0;
let policy =
Policy
.Handle<Exception>()
.WaitAndRetry(
sleepDurations = [| TimeSpan.FromSeconds(1.0) |],
onRetry = Action<Exception, TimeSpan>(fun _ _ -> proxyIndex <- proxyIndex + 1)
)
let makeCall () =
if (proxyIndex >= proxies.Length)
then failwith ("Exhausted proxies: " + String.Join(", ", proxies))
else
let proxy = WebProxy(proxies.[proxyIndex])
proxy.UseDefaultCredentials <- true
client.Proxy <- proxy
result <- client.DownloadString(new Uri(url));
policy.Execute(Action makeCall)
{ Result.Value = result; Proxy = proxies.[proxyIndex]}
您可以使用 Result<'TOk,'TError>
和 Async<T>
尝试更实用的方式
open System.Net
open System
type Request =
{ Url : string
Proxies : string list
UserName : string
Password : string }
let requestWithRetry request =
let client =
new WebClient (
Credentials = new NetworkCredential(
request.UserName,
request.Password))
let uri = Uri request.Url
let rec retry = function
| [] -> Error "Exhausted proxies" |> async.Return
| (proxy:string)::rest -> async {
try
do client.Proxy <- new WebProxy(proxy, UseDefaultCredentials = true)
let! response = client.AsyncDownloadString uri
return Ok (response, proxy)
with _ ->
do! Async.Sleep 1000
return! retry rest
}
retry request.Proxies
我正在使用 Polly 发出 HTTP 请求。我想在数组中的每个代理上等待 1 秒后重试一次。
我怎样才能做得更好?
我如何在 F# 中执行此操作?
public static Result RequestWithRetry(string url, string[] proxies, string username, string password)
{
if (proxies == null) throw new ArgumentNullException("null proxies array");
var client = new WebClient { Credentials = new NetworkCredential(username, password) };
var result = String.Empty;
var proxyIndex = 0;
var policy = Policy
.Handle<Exception>()
.WaitAndRetry(new[]
{
TimeSpan.FromSeconds(1)
}, (exception, timeSpan) => proxyIndex++);
policy.Execute(() =>
{
if (proxyIndex >= proxies?.Length) throw new Exception($"Exhausted proxies: {String.Join(", ", proxies)}");
client.Proxy = new WebProxy(proxies?[proxyIndex]) { UseDefaultCredentials = true };
result = client.DownloadString(new Uri(url));
});
return new Result(value: result, proxy: proxies[proxyIndex]);
}
我能够将这个翻译整合在一起。我不太喜欢它,尽管我确实在这个过程中学到了很多关于 F# 和 Action
的知识。
type Result = { Value: string; Proxy: string }
let request (proxies:string[]) (username:string) (password:string) (url:string) : Result =
if (proxies = null) then raise <| new ArgumentNullException()
use client = new WebClient()
client.Credentials <- NetworkCredential(username, password)
let mutable result = String.Empty;
let mutable proxyIndex = 0;
let policy =
Policy
.Handle<Exception>()
.WaitAndRetry(
sleepDurations = [| TimeSpan.FromSeconds(1.0) |],
onRetry = Action<Exception, TimeSpan>(fun _ _ -> proxyIndex <- proxyIndex + 1)
)
let makeCall () =
if (proxyIndex >= proxies.Length)
then failwith ("Exhausted proxies: " + String.Join(", ", proxies))
else
let proxy = WebProxy(proxies.[proxyIndex])
proxy.UseDefaultCredentials <- true
client.Proxy <- proxy
result <- client.DownloadString(new Uri(url));
policy.Execute(Action makeCall)
{ Result.Value = result; Proxy = proxies.[proxyIndex]}
您可以使用 Result<'TOk,'TError>
和 Async<T>
open System.Net
open System
type Request =
{ Url : string
Proxies : string list
UserName : string
Password : string }
let requestWithRetry request =
let client =
new WebClient (
Credentials = new NetworkCredential(
request.UserName,
request.Password))
let uri = Uri request.Url
let rec retry = function
| [] -> Error "Exhausted proxies" |> async.Return
| (proxy:string)::rest -> async {
try
do client.Proxy <- new WebProxy(proxy, UseDefaultCredentials = true)
let! response = client.AsyncDownloadString uri
return Ok (response, proxy)
with _ ->
do! Async.Sleep 1000
return! retry rest
}
retry request.Proxies