Skip to content

Commit

Permalink
Refactor to use timeout per Octokit API
Browse files Browse the repository at this point in the history
The issue referred in the code octokit/octokit.net#963
has since been fixed.

The timeout can be set via a method on the client, and per the last
comment octokit/octokit.net#963 (comment)
this needs to be set on the release upload request as well. If not set,
the default per-request timeout of 100 seconds is configured.
  • Loading branch information
csmager committed Apr 29, 2020
1 parent ae35979 commit d5880fa
Showing 1 changed file with 13 additions and 26 deletions.
39 changes: 13 additions & 26 deletions src/app/Fake.Api.GitHub/GitHub.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
open Octokit
open Octokit.Internal
open System
open System.Threading
open System.Net.Http
open System.Reflection
open System.IO

/// Contains tasks to interact with [GitHub](https://github.com/) releases
Expand Down Expand Up @@ -52,24 +49,10 @@ module GitHub =
/// If left unspecified, and the tag does not already exist, the default branch is used instead.
TargetCommitish : string }

// wrapper re-implementation of HttpClientAdapter which works around
// known Octokit bug in which user-supplied timeouts are not passed to HttpClient object
// https://github.com/octokit/octokit.net/issues/963
type private HttpClientWithTimeout(timeout : TimeSpan) as this =
inherit HttpClientAdapter(fun () -> HttpMessageHandlerFactory.CreateDefault())
let setter = lazy(
match typeof<HttpClientAdapter>.GetTypeInfo().GetField("_http", BindingFlags.NonPublic ||| BindingFlags.Instance) with
| null -> ()
| f ->
match f.GetValue(this) with
| :? HttpClient as http -> http.Timeout <- timeout
| _ -> ())

interface IHttpClient with
member __.Send(request : IRequest, ct : CancellationToken) =
setter.Force()
match request with :? Request as r -> r.Timeout <- timeout | _ -> ()
base.Send(request, ct)
let private timeout = TimeSpan.FromMinutes 20.

let private createHttpClient () =
new HttpClientAdapter(Func<_> HttpMessageHandlerFactory.CreateDefault)

/// A version of 'reraise' that can work inside computation expressions
let private captureAndReraise ex =
Expand Down Expand Up @@ -105,42 +88,46 @@ module GitHub =
/// Creates a GitHub API v3 client using the specified credentials
let createClient (user:string) (password:string) =
async {
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), httpClient)
let github = GitHubClient(connection)
github.Credentials <- Credentials(user, password)
github.SetRequestTimeout timeout
return github
}

/// Creates a GitHub API v3 client using the specified token
let createClientWithToken (token:string) =
async {
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), httpClient)
let github = GitHubClient(connection)
github.Credentials <- Credentials(token)
github.SetRequestTimeout timeout
return github
}

/// Creates a GitHub API v3 client to GitHub Enterprise server at the specified url using the specified credentials
let createGHEClient url (user:string) (password:string) =
async {
let credentials = Credentials(user, password)
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), Uri(url), InMemoryCredentialStore(credentials), httpClient, SimpleJsonSerializer())
let github = GitHubClient(connection)
github.Credentials <- credentials
github.SetRequestTimeout timeout
return github
}

/// Creates a GitHub API v3 client to GitHub Enterprise server at the specified url using the specified token
let createGHEClientWithToken url (token:string) =
async {
let credentials = Credentials(token)
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), Uri(url), InMemoryCredentialStore(credentials), httpClient, SimpleJsonSerializer())
let github = GitHubClient(connection)
github.Credentials <- credentials
github.SetRequestTimeout timeout
return github
}

Expand Down Expand Up @@ -209,7 +196,7 @@ module GitHub =
| None -> ()

let archiveContents = File.OpenRead(fi.FullName)
let assetUpload = ReleaseAssetUpload(fi.Name,"application/octet-stream",archiveContents,Nullable<TimeSpan>())
let assetUpload = ReleaseAssetUpload(fi.Name,"application/octet-stream",archiveContents,Nullable timeout)

let! asset = Async.AwaitTask <| release'.Client.Repository.Release.UploadAsset(release'.Release, assetUpload)
printfn "Uploaded %s" asset.Name
Expand Down

0 comments on commit d5880fa

Please sign in to comment.