Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't retry too much in Octokit.fsx #942

Merged
merged 2 commits into from
Sep 11, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions modules/Octokit/Octokit.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type Draft =

let private isRunningOnMono = System.Type.GetType ("Mono.Runtime") <> null

/// A version of 'reraise' that can work inside computation expressions
let private captureAndReraise ex =
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw()
Unchecked.defaultof<_>

/// Retry the Octokit action count times
let rec private retry count asyncF =
// This retry logic causes an exception on Mono:
// https://github.com/fsharp/fsharp/issues/440
Expand All @@ -24,9 +30,25 @@ let rec private retry count asyncF =
async {
try
return! asyncF
with _ when count > 0 -> return! retry (count - 1) asyncF
with ex ->
return!
match (ex, ex.InnerException) with
| (:? AggregateException, (:? AuthorizationException as ex)) -> captureAndReraise ex
| _ when count > 0 -> retry (count - 1) asyncF
| (ex, _) -> captureAndReraise ex
}

/// Retry the Octokit action count times after input succeed
let private retryWithArg count input asycnF =
async {
let! choice = input |> Async.Catch
match choice with
| Choice1Of2 input' ->
return! (asycnF input') |> retry count
| Choice2Of2 ex ->
return captureAndReraise ex
}

let createClient user password =
async {
let github = new GitHubClient(new ProductHeaderValue("FAKE"))
Expand All @@ -42,41 +64,39 @@ let createClientWithToken token =
}

let private makeRelease draft owner project version prerelease (notes:seq<string>) (client : Async<GitHubClient>) =
async {
retryWithArg 5 client <| fun client' -> async {
let data = new NewRelease(version)
data.Name <- version
data.Body <- String.Join(Environment.NewLine, notes)
data.Draft <- draft
data.Prerelease <- prerelease
let! client' = client
let! draft = Async.AwaitTask <| client'.Release.Create(owner, project, data)
let draftWord = if data.Draft then " draft" else ""
printfn "Created%s release id %d" draftWord draft.Id
return { Client = client'
Owner = owner
Project = project
DraftRelease = draft }
} |> retry 5
return {
Client = client'
Owner = owner
Project = project
DraftRelease = draft }
}

let createDraft owner project version prerelease notes client = makeRelease true owner project version prerelease notes client
let createRelease owner project version prerelease notes client = makeRelease false owner project version prerelease notes client

let uploadFile fileName (draft : Async<Draft>) =
async {
retryWithArg 5 draft <| fun draft' -> async {
let fi = FileInfo(fileName)
let archiveContents = File.OpenRead(fi.FullName)
let assetUpload = new ReleaseAssetUpload(fi.Name,"application/octet-stream",archiveContents,Nullable<TimeSpan>())
let! draft' = draft
let! asset = Async.AwaitTask <| draft'.Client.Release.UploadAsset(draft'.DraftRelease, assetUpload)
printfn "Uploaded %s" asset.Name
return draft'
} |> retry 5
}

let releaseDraft (draft : Async<Draft>) =
async {
let! draft' = draft
retryWithArg 5 draft <| fun draft' -> async {
let update = draft'.DraftRelease.ToUpdate()
update.Draft <- Nullable<bool>(false)
let! released = Async.AwaitTask <| draft'.Client.Release.Edit(draft'.Owner, draft'.Project, draft'.DraftRelease.Id, update)
printfn "Released %d on github" released.Id
} |> retry 5
}