github.com/Benchkram/bob@v0.0.0-20220321080157-7c8f3876e225/pkg/ctl/control.go (about)

     1  package ctl
     2  
     3  import (
     4  	"io"
     5  )
     6  
     7  type Control interface {
     8  	Command
     9  
    10  	Control() <-chan Signal
    11  
    12  	EmitDone()
    13  	EmitStopped()
    14  	EmitStarted()
    15  	EmitRestarted()
    16  	EmitError(error)
    17  }
    18  
    19  // assert control implements the Command & Control interface
    20  var _ Command = (*control)(nil)
    21  var _ Control = (*control)(nil)
    22  
    23  type control struct {
    24  	name string
    25  
    26  	stdout io.Reader
    27  	stderr io.Reader
    28  	stdin  io.Writer
    29  
    30  	ctl       chan Signal
    31  	done      chan struct{}
    32  	started   chan struct{}
    33  	stopped   chan struct{}
    34  	restarted chan struct{}
    35  	err       chan error
    36  }
    37  
    38  func (c *control) Running() bool {
    39  	// TODO: @Tasos that needs to be somehow implemented for the TUI
    40  	//panic("implement me")
    41  	return true
    42  
    43  }
    44  
    45  // New takes the size of the control channel.
    46  // Usually this should be 0 so that signals are ignored as long
    47  // as a start/stop is in progress.
    48  func New(name string, bufferedctl int, stdout, stderr io.Reader, stdin io.Writer) Control {
    49  	return &control{
    50  		name: name,
    51  
    52  		stdout: stdout,
    53  		stderr: stderr,
    54  		stdin:  stdin,
    55  
    56  		// ctl recives external signals
    57  		ctl: make(chan Signal, bufferedctl),
    58  
    59  		started:   make(chan struct{}, 1),
    60  		stopped:   make(chan struct{}, 1),
    61  		restarted: make(chan struct{}, 1),
    62  		done:      make(chan struct{}),
    63  
    64  		err: make(chan error, 1),
    65  	}
    66  }
    67  
    68  // Name of the service the runCtrl controls
    69  func (c *control) Name() string {
    70  	return c.name
    71  }
    72  
    73  func (c *control) Start() (err error) {
    74  	select {
    75  	case c.ctl <- Start:
    76  	default:
    77  		return nil // Ignoring signal
    78  	}
    79  
    80  	select {
    81  	case <-c.started:
    82  	case e := <-c.err:
    83  		return e
    84  	}
    85  
    86  	return nil
    87  }
    88  
    89  func (c *control) Stop() (err error) {
    90  	select {
    91  	case c.ctl <- Stop:
    92  	default:
    93  		return nil // Ignoring signal
    94  	}
    95  
    96  	select {
    97  	case <-c.stopped:
    98  	case e := <-c.err:
    99  		return e
   100  	}
   101  
   102  	return nil
   103  }
   104  
   105  func (c *control) Shutdown() (err error) {
   106  	select {
   107  	case c.ctl <- Shutdown:
   108  	default:
   109  		return nil
   110  	}
   111  
   112  	select {
   113  	case <-c.done:
   114  	case e := <-c.err:
   115  		return e
   116  	}
   117  
   118  	return nil
   119  }
   120  
   121  func (c *control) Restart() (err error) {
   122  	select {
   123  	case c.ctl <- Restart:
   124  	default:
   125  		return nil
   126  	}
   127  
   128  	select {
   129  	case <-c.restarted:
   130  	case e := <-c.err:
   131  		return e
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func (c *control) Control() <-chan Signal {
   138  	return c.ctl
   139  }
   140  func (c *control) Done() <-chan struct{} {
   141  	return c.done
   142  }
   143  
   144  func (c *control) Error() <-chan error {
   145  	return c.err
   146  }
   147  
   148  // EmitStop signals that the cmd has finished.
   149  func (c *control) EmitDone() {
   150  	close(c.done)
   151  }
   152  
   153  // EmitStarted signals that the cmd has been started.
   154  func (c *control) EmitStarted() {
   155  	select {
   156  	case c.started <- struct{}{}:
   157  	default:
   158  	}
   159  }
   160  
   161  // EmitRestarted signals that the cmd has been restarted.
   162  func (c *control) EmitRestarted() {
   163  	select {
   164  	case c.restarted <- struct{}{}:
   165  	default:
   166  	}
   167  }
   168  
   169  // EmitStop signals that the cmd has stopped
   170  // and can be restarted.
   171  func (c *control) EmitStopped() {
   172  	select {
   173  	case c.stopped <- struct{}{}:
   174  	default:
   175  	}
   176  }
   177  
   178  // EmitError emits a error to the error channel.
   179  func (c *control) EmitError(err error) {
   180  	select {
   181  	case c.err <- err:
   182  	default:
   183  	}
   184  }
   185  
   186  func (c *control) Stdout() io.Reader {
   187  	return c.stdout
   188  }
   189  
   190  func (c *control) Stderr() io.Reader {
   191  	return c.stderr
   192  }
   193  
   194  func (c *control) Stdin() io.Writer {
   195  	return c.stdin
   196  }