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 }