Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Commit ade3636

Browse files
committed
Add support for executing inner tasks
1 parent 32af385 commit ade3636

2 files changed

Lines changed: 25 additions & 7 deletions

File tree

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project ToolsVersion="15.0">
22
<PropertyGroup>
3-
<VersionPrefix>0.0.3</VersionPrefix>
3+
<VersionPrefix>0.0.4</VersionPrefix>
44
<Authors>@jet @bartelink and contributors</Authors>
55
<Company>Jet.com</Company>
66
<Description>Apply systemwide resilience strategies consistently across subsystems, standing on Polly's shoulders</Description>
@@ -9,6 +9,6 @@
99
<RepositoryType>git</RepositoryType>
1010
<PackageTags>polly bulkhead circuitbreaker timeout fsharp</PackageTags>
1111
<PackageLicenseUrl>https://github.com/jet/CallPolly/blob/master/LICENSE</PackageLicenseUrl>
12-
<Copyright>Copyright © 2018</Copyright>
12+
<Copyright>Copyright © 2018</Copyright>
1313
</PropertyGroup>
1414
</Project>

src/CallPolly/Rules.fs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ type PolicyConfig = { isolate: bool; cutoff: CutoffConfig option; limit: Bulkhea
1919

2020
type GovernorState = { circuitState : string option; bulkheadAvailable : int option; queueAvailable : int option }
2121

22+
[<NoComparison; NoEquality>]
23+
[<RequireQualifiedAccess>]
24+
type TaskOrAsync<'T> =
25+
| Task of (CancellationToken -> Task<'T>)
26+
| Async of (Async<'T>)
27+
2228
/// Translates a PolicyConfig's rules to a Polly IAsyncPolicy instance that gets held in the ActionPolicy
2329
type Governor(log: Serilog.ILogger, buildFailurePolicy: unit -> Polly.PolicyBuilder, serviceName: string, callName: string, policyName: string, config: PolicyConfig) =
2430
let logBreach sla interval = log |> Events.Log.cutoffSlaBreached (serviceName, callName, policyName) sla interval
@@ -115,9 +121,14 @@ type Governor(log: Serilog.ILogger, buildFailurePolicy: unit -> Polly.PolicyBuil
115121
Some () // Compiler gets too clever if we never return Some
116122

117123
/// Execute and/or log failures regarding invocation of a function with the relevant policy applied
118-
member __.Execute(inner : Async<'a>) : Async<'a> =
124+
member __.Execute(inner: TaskOrAsync<'a>) : Async<'a> =
119125
match asyncPolicy with
120-
| None -> inner
126+
| None ->
127+
match inner with
128+
| TaskOrAsync.Async a -> a
129+
| TaskOrAsync.Task factory -> async {
130+
let! ct = Async.CancellationToken
131+
return! factory ct |> Async.AwaitTaskCorrect }
121132
| Some polly -> async {
122133
let mutable wasFull = false
123134
// NB This logging is on a best-effort basis - obviously the guard here has an implied race condition
@@ -154,7 +165,10 @@ type Governor(log: Serilog.ILogger, buildFailurePolicy: unit -> Polly.PolicyBuil
154165

155166
// sic - cancellation of the inner computation needs to be controlled by Polly's chain of handlers
156167
// for example, if a cutoff is configured, it's Polly that will be requesting the cancellation
157-
Async.StartAsTask(inner, cancellationToken=pollyCt)
168+
match inner with
169+
| TaskOrAsync.Async a -> Async.StartAsTask(a, cancellationToken=pollyCt)
170+
| TaskOrAsync.Task factory -> factory pollyCt
171+
158172
let execute = async {
159173
let! ct = Async.CancellationToken // Grab async cancellation token of this `Execute` call, so cancellation gets propagated into the Polly [wrap]
160174
try return! polly.ExecuteAsync(startInnerTask, ct) |> Async.AwaitTaskCorrect
@@ -209,9 +223,13 @@ type CallPolicy<'TConfig when 'TConfig: equality> (makeGoverner : CallConfig<'TC
209223
member __.Policy = cfg.policy
210224
member __.Config = cfg.config
211225

212-
/// Execute the call, apply the policy rules
226+
/// Execute an inner Async computation, applying the policy rules
213227
member __.Execute(inner : Async<'t>) =
214-
governor.Execute inner
228+
governor.Execute (TaskOrAsync.Async inner)
229+
230+
/// Execute an inner Task-Method, applying the policy rules
231+
member __.ExecuteTask<'T>(inner : CancellationToken -> Task<'T>) =
232+
governor.Execute (TaskOrAsync.Task inner)
215233

216234
/// Facilitates dumping for diagnostics
217235
member __.InternalState =

0 commit comments

Comments
 (0)