Pholly icon indicating copy to clipboard operation
Pholly copied to clipboard

Add timeout (async) policy.

Open deapsquatter opened this issue 3 years ago • 1 comments

deapsquatter avatar Sep 05 '22 10:09 deapsquatter

Wish I'd checked here before I implemented this myself :facepalm:

My implementation differed slightly though as I caught the exception thrown by a timed-out policy and returned a Result<'t, exn>. I also created a variation that flat-mapped a Task<Result<'t, exn>> too.

While I didn't implement the same builder API as the rest of the library (I didn't need it), here's my example:

module Policy =
    let timeout (duration: int<ms>) : (CancellationToken -> 't) -> Result<'t, exn> =
        fun workload ->
            let ts = TimeSpan.FromMilliseconds (double duration)
            let ct = CancellationToken.None
            let policy = Polly.Policy.Timeout ts

            try
                policy.Execute (workload, ct) |> Ok
            with :? Polly.Timeout.TimeoutRejectedException as e ->
                Error e

    let timeoutResult (duration: int<ms>) : (CancellationToken -> Result<'t, exn>) -> Result<'t, exn> =
        fun workload ->
            let ts = TimeSpan.FromMilliseconds (double duration)
            let ct = CancellationToken.None
            let policy = Polly.Policy.Timeout ts

            try
                policy.Execute (workload, ct)
            with :? Polly.Timeout.TimeoutRejectedException as e ->
                Error e

    let timeoutAsync (duration: int<ms>) : (CancellationToken-> Task<'t>) -> Task<Result<'t, exn>> =
        fun asyncWorkload -> task {
            let ts = TimeSpan.FromMilliseconds (double duration)
            let ct = CancellationToken.None
            let policy = Polly.Policy.TimeoutAsync ts

            try
                let! res = policy.ExecuteAsync (asyncWorkload, ct)
                return Ok res
            with :? Polly.Timeout.TimeoutRejectedException as e ->
                return Error e
        }

    let timeoutAsyncResult (duration: int<ms>) : (CancellationToken -> Task<Result<'t, exn>>) -> Task<Result<'t, exn>> =
        fun asyncWorkload -> task {
            let ts = TimeSpan.FromMilliseconds (double duration)
            let ct = CancellationToken.None
            let policy = Polly.Policy.TimeoutAsync ts

            try
                return! policy.ExecuteAsync (asyncWorkload, ct)
            with :? Polly.Timeout.TimeoutRejectedException as e ->
                return Error e
        }

Just FYI, I don't think the composition operator will work with either implementation --|> (at least, on the right-hand side) but you can get around this by wrapping the policy in a function instead of composing like this.

Would be good if we could get your input @JamesRandall as it would help provide a more complete API coverage.

Awesome work on this wrapper - Makes life a lot easier!

Cheers, James.

absolutejam avatar Sep 22 '22 15:09 absolutejam