BasicService implements contract of Service interface, using three supplied functions: StartingFn, RunningFn and StoppingFn. When service is started, these three functions are called as service transitions to Starting, Running and Stopping state. Since they are called sequentially, they don't need
| 50 | // * 1. StartingFn, 2. RunningFn, 3. StoppingFn -- this is most common, when StartingFn doesn't return error, |
| 51 | // service is not stopped and context isn't stopped externally while running StartingFn. |
| 52 | type BasicService struct { |
| 53 | // functions only run, if they are not nil. If functions are nil, service will effectively do nothing |
| 54 | // in given state, and go to the next one without any error. |
| 55 | startFn StartingFn |
| 56 | runningFn RunningFn |
| 57 | stoppingFn StoppingFn |
| 58 | |
| 59 | // everything below is protected by this mutex |
| 60 | stateMu sync.RWMutex |
| 61 | state State |
| 62 | failureCase error |
| 63 | listeners []chan func(l Listener) |
| 64 | serviceName string |
| 65 | |
| 66 | // closed when state reaches Running, Terminated or Failed state |
| 67 | runningWaitersCh chan struct{} |
| 68 | // closed when state reaches Terminated or Failed state |
| 69 | terminatedWaitersCh chan struct{} |
| 70 | |
| 71 | serviceContext context.Context |
| 72 | serviceCancel context.CancelFunc |
| 73 | } |
| 74 | |
| 75 | func invalidServiceStateError(state, expected State) error { |
| 76 | return fmt.Errorf("invalid service state: %v, expected: %v", state, expected) |
nothing calls this directly
no outgoing calls
no test coverage detected