Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to code a "retry" logic (with only 1 iteration) in F# without mutable vars?

Tags:

f#

refactoring

So by trying to avoid mutable variables, I came up with the following retry-logic code, which seems ugly:

let result = TryConnect()
match result with
| ErrorConnecting ->
    SetupConnectionParameters()
    let resultAgain = TryConnect()
    match resultAgain with
    | ErrorConnecting ->
                      Console.Error.WriteLine("Setup failed!")
                      Environment.Exit(7)
    | Success(value) -> PerformOperations(value)
| Success(value) -> PerformOperations(value)

Is there a way to reduce some duplication here? (Remember, no mutable vars.) Thanks!

like image 873
ympostor Avatar asked Jul 19 '16 10:07

ympostor


People also ask

What is a retry logic?

Retry logic is implemented whenever there is a failing operation. Implement retry logic only where the full context of a failing operation. It's important to log all connectivity failures that cause a retry so that underlying problems with the application, services, or resources can be identified.

How does retry work in Python?

retrying provides a decorator called retry that you can use on top of any function or method in Python to make it retry in case of failure. By default, retry calls your function endlessly until it returns rather than raising an error. This will execute the function pick_one until 1 is returned by random.

Is try except good practice?

WARNING! Try-except statements should never be used in place of good programming practice. For example, you should not code sloppily and then encase your program in a try-except statement until you have taken every measure you can think of to ensure that your function is working properly.


2 Answers

Since there are a lot of alternatives being shown here, here is another one:

let private tryConnectNth n = 
    if n <> 0 then SetupConnectionParameters()
    TryConnect()

let isSuccess = function
    |Success _ -> true
    |ErrorConnecting -> false

let tryConnect n =
    Seq.init n tryConnectNth // generate a sequence of n connection attempts
    |> Seq.tryFind isSuccess // try to find the first success - returns Option
    |> Option.fold (fun _ -> id) ErrorConnecting // return ErrorConnecting if None, or result otherwise

It calls SetupConnectionParameters() only on a non-zero connection attempt and repeats up to n times.

like image 142
TheInnerLight Avatar answered Sep 30 '22 19:09

TheInnerLight


Make the function recursive with a parameter for retries:

let rec private tryToConnectAux tryAgain =
    match TryConnect() with
    | Success(value) -> PerformOperations(value)
    | ErrorConnecting when tryAgain ->
        SetupConnectionParameters ()
        tryToConnectAux false
    | ErrorConnecting ->
        Console.Error.WriteLine("Setup failed!")
        Environment.Exit(7)

Call via tryToConnectAux true.


This answer was edited. Original code:

let rec tryConnecting nRetries =
    match TryConnect() with
    | ErrorConnecting ->
        if nRetries > 0 then tryConnecting (nRetries - 1)
        else
            Console.Error.WriteLine("Setup failed!")
            Environment.Exit(7)
    | Success(value) -> PerformOperations(value)

(This version doesn't include SetupConnectionParameters(), you have to add it at whatever location is appropriate)

like image 37
Vandroiy Avatar answered Sep 30 '22 18:09

Vandroiy