mercredi 31 août 2016

Circuit breaker design pattern sleep vs time.AfterFunc

I am trying to create a Circuit breaker pattern, I want to execute a command exec.Command and if it fails, retry in X defined amount of time, for testing purposes, I am doing something like this for testing time.AfterFunc:

package main

import (
    "fmt"
    "time"
)

func myFunc() error {
    for i := 1; i < 10; i++ {
        fmt.Printf("i = %+v\n", i)
        if i%3 == 0 {
            return fmt.Errorf("error")
        }
    }
    return nil
}

func main() {

    run := make(chan struct{}, 1)

    run <- struct{}{}

    for {
        select {
        case <-run:
            err := myFunc()
            if err != nil {
                time.AfterFunc(3*time.Second, func() {
                    run <- struct{}{}
                })
            }
        default:
        }
    }
}

time.AfterFunc works for the above code, but not for the example below, I had to replace it with a sleep in order to achieve the expected results:

package main

import (
    "fmt"
    "os/exec"
    "time"
)

func Exec(done chan<- error) error {
    cmd := exec.Command("./start")
    if err := cmd.Start(); err != nil {
        return err
    }
    go func() {
        done <- cmd.Wait()
    }()
    return nil
}

func main() {
    var (
        run  = make(chan struct{}, 1)
        done = make(chan error, 1)
    )

    Exec(done)

    for {
        select {
        case <-run:
            err := Exec(done)
            if err != nil {
                fmt.Println(err)
                // time.AfterFunc(3*time.Second, func() {
                time.Sleep(3 * time.Second)
                run <- struct{}{}
            }
        default:
            select {
            case err := <-done:
                fmt.Println(err)
                run <- struct{}{}
            }
        }
    }
}

The content of ./sleep:

#!/bin/sh

sleep 3

And for testing, creating an error, I toggle perms:

chmod -x sleep
chmod +x sleep

Therefore wondering what are the differences between using time.AfterFunc and time.Sleep and what could be the best way of implementing this pattern.

Aucun commentaire:

Enregistrer un commentaire