github.com/go-graphite/carbonapi@v0.17.0/cmd/mockbackend/runner.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "os/exec" 7 "sync" 8 9 "github.com/tevino/abool" 10 "go.uber.org/zap" 11 ) 12 13 type runner struct { 14 App 15 16 out string 17 18 isRunning *abool.AtomicBool 19 ctx context.Context 20 cancel context.CancelFunc 21 logger *zap.Logger 22 wg sync.WaitGroup 23 } 24 25 func new(config *App, logger *zap.Logger) *runner { 26 r := &runner{ 27 App: *config, 28 logger: logger.With( 29 zap.String("name", config.Name), 30 ), 31 isRunning: abool.New(), 32 } 33 34 return r 35 } 36 37 func (r *runner) Run() { 38 r.wg.Add(1) 39 defer r.wg.Done() 40 41 if !r.isRunning.SetToIf(false, true) { 42 r.logger.Fatal("app is already running") 43 } 44 r.logger.Debug("will start application", 45 zap.Any("config", r.App), 46 ) 47 r.ctx, r.cancel = context.WithCancel(context.Background()) 48 49 cmd := exec.CommandContext(r.ctx, r.Binary, r.Args...) 50 out, err := cmd.CombinedOutput() 51 r.out = string(out) 52 if err != nil { 53 r.logger.Error("error running program", 54 zap.Any("config", r.App), 55 zap.String("output", "will follow next"), 56 zap.Error(err), 57 ) 58 fmt.Print(r.out) 59 } 60 61 r.isRunning.UnSet() 62 } 63 64 func (r *runner) Finish() { 65 r.cancel() 66 r.wg.Wait() 67 } 68 69 func (r *runner) IsRunning() bool { 70 return r.isRunning.IsSet() 71 } 72 73 func (r *runner) Out() string { 74 return r.out 75 }