Έχουν δημοσιευτεί Κυριακή, 10 Οκτωβρίου 2010 6:41 μμ από το μέλος PALLADIN

Monadic Retry

Πολλές φορες έχουμε σενάρια που θα θέλαμε να εφαρμοσουμε συγκεκριμενα retry policies σε error prone computations.
Τα σενάρια αυτά εμφανίζονται αρκετά συχνά και κυρίως σε cloud computations.
Στο Azure για παράδειγμα, υπάρχουν και συγκεκριμένα APIs που παίζουν με Retry Policies.

Το παρακάτω monad είναι μια έμπνευση που είχα στο να κάνω combine το
reader monad (για το propagation του policy) μαζί με το exception monad έτσι ώστε να δομήσω ένα retry monad.

open System
open System.Threading
 
type ShouldRetry = ShouldRetry of (RetryCount * LastException -> bool * RetryDelay)
and RetryCount = int
and LastException = exn
and RetryDelay = TimeSpan
type RetryPolicy = RetryPolicy of ShouldRetry
   
type RetryPolicies() =
    static member NoRetry () : RetryPolicy =
        RetryPolicy( ShouldRetry (fun (retryCount, _) -> (retryCount < 1, TimeSpan.Zero)) )
    static member Retry (currentRetryCount : int , intervalBewteenRetries : RetryDelay) : RetryPolicy =
        RetryPolicy( ShouldRetry (fun (retryCount, _) -> (currentRetryCount < retryCount, intervalBewteenRetries)))
    static member Retry (currentRetryCount : int) : RetryPolicy =
        RetryPolicies.Retry(currentRetryCount, TimeSpan.Zero)
 
type RetryResult<'a> =
    | RetrySuccess of 'a
    | RetryFailure of exn
   
// Reader + Exception Monad DataType
type Retry<'a> = Retry of (RetryPolicy -> RetryResult<'a>)
 
type RetryBuilder() =
    member self.Return (value : 'a) : Retry<'a> = Retry (fun retryPolicy -> RetrySuccess value)
 
    member self.Bind (retry : Retry<'a>, bindFunc : 'a -> Retry<'b>) : Retry<'b> =
        Retry (fun retryPolicy ->
            let (Retry retryFunc) = retry
            match retryFunc retryPolicy with
            | RetrySuccess value ->
                let (Retry retryFunc') = bindFunc value
                retryFunc' retryPolicy
            | RetryFailure exn -> RetryFailure exn )
 
    member self.Delay (f : unit -> Retry<'a>) : Retry<'a> =
        Retry (fun retryPolicy ->
            let mutable resultCell : option<RetryResult<'a>> = None
            let mutable lastExceptionCell : exn = null
            let (RetryPolicy(ShouldRetry shouldRetry)) = retryPolicy
            let mutable canRetryCell : bool = true
            let mutable currentRetryCountCell : int = 0
            while canRetryCell do
                try
                    let (Retry retryFunc) = f ()
                    let result = retryFunc retryPolicy
                    resultCell <- Some result
                    canRetryCell <- false
                with e ->
                    lastExceptionCell <- e
                    currentRetryCountCell <- 1 + currentRetryCountCell
                    match shouldRetry(currentRetryCountCell, lastExceptionCell) with
                    | (true, retryDelay) ->
                        canRetryCell <- true
                        Thread.Sleep(retryDelay)
                    | (false, _) -> canRetryCell <- false
 
            match resultCell with
            | Some result -> result
            | None -> RetryFailure lastExceptionCell )
 
[<AutoOpen>]
module Retry =
    let retry = new RetryBuilder()
    // override default policy
    let retryWithPolicy (retryPolicy : RetryPolicy) (retry : Retry<'a>) =
        Retry (fun _ -> let (Retry retryFunc) = retry in retryFunc retryPolicy)

    let run (retry : Retry<'a>) (retryPolicy : RetryPolicy) : RetryResult<'a> =
        let (Retry retryFunc) = retry
        retryFunc retryPolicy

// DivByzero example
let rnd = System.Random()
let example = 
    retry {
        let! a = retry { return 1 / rnd.Next(0, 2) }
        let! b = retry { return 2 / rnd.Next(0, 2) }
        // override default policy
        let! c = retryWithPolicy (RetryPolicies.NoRetry()) (retry { return 3 / rnd.Next(0, 2) })

        return a * b * c
    }
run example (RetryPolicies.Retry 1)


Share


Ενημέρωση για Σχόλια

Αν θα θέλατε να λαμβάνετε ένα e-mail όταν γίνονται ανανεώσεις στο περιεχόμενο αυτής της δημοσίευσης, παρακαλούμε γίνετε συνδρομητής εδώ

Παραμείνετε ενήμεροι στα τελευταία σχόλια με την χρήση του αγαπημένου σας RSS Aggregator και συνδρομή στη Τροφοδοσία RSS με σχόλια

Σχόλια:

Χωρίς Σχόλια

Ποιά είναι η άποψή σας για την παραπάνω δημοσίευση;

(απαιτούμενο)
απαιτούμενο
προαιρετικό
απαιτούμενο
ÅéóÜãåôå ôïí êùäéêü:
CAPTCHA Image