@@ -9,18 +9,17 @@ type private ZkbApiPassthroughActorState = {
9
9
with
10
10
static member empty = { ZkbApiPassthroughActorState.lastZkbRequest = DateTime.MinValue }
11
11
12
- type ZkbApiPassthroughActor ( log : PostMessage )=
12
+ type ZkbApiPassthroughActor ( config : Configuration , log : PostMessage )=
13
13
let logSource = typeof< ZkbApiPassthroughActor>. Name
14
14
let logException ( ex : Exception ) = ( logSource, ex.Message) |> ActorMessage.Error |> log
15
15
let logInfo ( msg : string ) = ( logSource, msg) |> ActorMessage.Info |> log
16
-
16
+
17
17
let logGetRequest ( path : string ) = sprintf " Sending GET %s " path |> logInfo
18
18
let logGetResp ( resp : HttpResponseMessage ) = sprintf " Received %A from %A " resp.StatusCode resp.RequestMessage.RequestUri |> logInfo
19
19
20
20
let httpClient = Web.httpClient()
21
-
22
- [<Literal>]
23
- let zkbDomain = " https://zkillboard.com/api"
21
+ let zkbBaseUri = if config.ZkbApiBaseUri.EndsWith( " /" ) then config.ZkbApiBaseUri
22
+ else config.ZkbApiBaseUri + " /"
24
23
25
24
let getResponseString ( resp : HttpResponseMessage )= resp.Content.ReadAsStringAsync() |> Async.AwaitTask |> Async.RunSynchronously
26
25
@@ -39,27 +38,45 @@ type ZkbApiPassthroughActor(log: PostMessage)=
39
38
| System.Net.HttpStatusCode.NotFound -> { WebResponse.Status = HttpStatus.NotFound; Retry = None; Message = " " }
40
39
| System.Net.HttpStatusCode.TooManyRequests -> { WebResponse.Status = HttpStatus.TooManyRequests; Retry = None; Message = " " }
41
40
| System.Net.HttpStatusCode.Forbidden -> { WebResponse.Status = HttpStatus.Forbidden; Retry = None; Message = " " }
42
- | _ -> { WebResponse.Status = HttpStatus.Error; Retry = None; Message = " " }
41
+ | _ -> { WebResponse.Status = HttpStatus.Error; Retry = None; Message = " Unknown error. " }
43
42
44
43
return result
45
44
with
46
45
| ex -> logException ex
47
- return { WebResponse.Status = HttpStatus.Error; Retry = None; Message = " " }
46
+ return { WebResponse.Status = HttpStatus.Error; Retry = None; Message = ex.Message }
48
47
}
49
48
50
49
let getZkbApi ( path : string ) ( lastZkbRequest : DateTime ) =
51
- async {
52
- let diff = DateTime.UtcNow - lastZkbRequest
53
- if diff < TimeSpan.FromSeconds( 1. ) then
54
- diff |> sprintf " Last Zkb API request in %A : pausing." |> logInfo
55
- do ! Async.Sleep( 1000 )
56
-
57
- let domain = if path.StartsWith( " /" ) then zkbDomain
58
- else zkbDomain + " /"
59
-
60
- return ! sprintf " %s%s " domain path |> getAsync
50
+ let maxIterations = 10
51
+
52
+ let rec get ( url : string ) ( lastZkbRequest : DateTime ) iterations =
53
+ async {
54
+ let diff = DateTime.UtcNow - lastZkbRequest
55
+ if diff < TimeSpan.FromSeconds( 1. ) then
56
+ diff |> sprintf " Last Zkb API request in %A : pausing." |> logInfo
57
+ do ! Async.Sleep( 1000 )
58
+
59
+ let! resp = getAsync url
60
+
61
+ return !
62
+ match resp.Status with
63
+ | HttpStatus.TooManyRequests when iterations <= 0 ->
64
+ async { return { WebResponse.Status = HttpStatus.Error; Retry = None;
65
+ Message = maxIterations |> sprintf " Retried after %i iterations, quitting." } }
66
+ | HttpStatus.TooManyRequests ->
67
+ iterations |> sprintf " Retrying, %i iteration(s) left." |> logInfo
68
+ get url DateTime.UtcNow ( iterations - 1 )
69
+ | _ -> async { return resp }
70
+
61
71
}
62
72
73
+ let path = if path.StartsWith( " /" ) then path.Substring( 1 )
74
+ else path
75
+ let uri = sprintf " %s%s " zkbBaseUri path
76
+
77
+ get uri lastZkbRequest maxIterations
78
+
79
+
63
80
let pipe = MessageInbox.Start( fun inbox ->
64
81
let rec loop ( state : ZkbApiPassthroughActorState ) = async {
65
82
let! msg = inbox.Receive()
0 commit comments