Превратите политику повторных попыток в функцию многократного использования - PullRequest
0 голосов
/ 24 апреля 2019

У нас есть простая политика повторов для нашего проекта:

  1. При первой ошибке спите в течение 1 секунды.
  2. При второй ошибке спите 5 секунд.
  3. При третьей ошибке спите 10 секунд.
  4. При четвертой ошибке выйдите из повторной попытки и верните ошибку.

Вот как выглядит наша политика повторов:

package main

import (
    "errors"  
    "fmt"         
    "time"    
)

func main() {
    errorCount := 0
    var err error

    fmt.Println("start!")

    for {
        err = generateError()
        if err != nil {
            if errorCount == 0 {
                fmt.Println("sleeping for 1 second...")
                time.Sleep(1 * time.Second)    
            } else if errorCount == 1 {
                fmt.Println("sleeping for 5 seconds...")
                time.Sleep(5 * time.Second)    
            } else if errorCount == 2 {
                fmt.Println("sleeping for 10 seconds...")
                time.Sleep(10 * time.Second)    
            } else {
                fmt.Println("giving up...")
                break
            }

            errorCount++
        } else {
            fmt.Println("no errors!")
            break
        }
    }

    fmt.Println("error:", err)
    fmt.Println("done!")
}

func generateError() error {
    err := errors.New("something happened")
    return err
}

Есть ли способпревратить приведенный выше код в функцию многократного использования?

1 Ответ

4 голосов
/ 24 апреля 2019

Просто передайте generateError в качестве аргумента (я упростил функцию повтора, потому что ничего не мог с собой поделать):

package main

import (
    "errors"
    "fmt"
    "time"
)

func main() {
    retry(generateError)
}

func retry(f func() error) {
    fmt.Println("start!")

    backoff := []time.Duration{
        1 * time.Second,
        5 * time.Second,
        10 * time.Second,
    }

    var err error
    for _, d := range backoff {
        err = f()
        if err != nil {
            fmt.Printf("sleeping for %v...\n", d)
            time.Sleep(d)
        } else {
            fmt.Println("no errors!")
            return
        }
    }

    fmt.Println("error:", err)
    fmt.Println("done!")
}

func generateError() error {
    err := errors.New("something happened")
    return err
}
...