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  }