This is the "main" method, that does most of the work of service. Service is in Starting state when this method runs. Entire lifecycle of the service happens here.
()
| 154 | // Service is in Starting state when this method runs. |
| 155 | // Entire lifecycle of the service happens here. |
| 156 | func (b *BasicService) main() { |
| 157 | var err error |
| 158 | |
| 159 | if b.startFn != nil { |
| 160 | err = b.startFn(b.serviceContext) |
| 161 | } |
| 162 | |
| 163 | if err != nil { |
| 164 | b.mustSwitchState(Starting, Failed, func() { |
| 165 | b.failureCase = err |
| 166 | b.serviceCancel() // cancel the context, just in case if anything started in StartingFn is using it |
| 167 | // we will not reach Running or Terminated, notify waiters |
| 168 | close(b.runningWaitersCh) |
| 169 | close(b.terminatedWaitersCh) |
| 170 | b.notifyListeners(func(l Listener) { l.Failed(Starting, err) }, true) |
| 171 | }) |
| 172 | return |
| 173 | } |
| 174 | |
| 175 | stoppingFrom := Starting |
| 176 | |
| 177 | // Starting has succeeded. We should switch to Running now, but let's not do that |
| 178 | // if our context has been canceled in the meantime. |
| 179 | if err = b.serviceContext.Err(); err != nil { |
| 180 | err = nil // don't report this as a failure, it is a normal "stop" signal. |
| 181 | goto stop |
| 182 | } |
| 183 | |
| 184 | // We have reached Running state |
| 185 | b.mustSwitchState(Starting, Running, func() { |
| 186 | // unblock waiters waiting for Running state |
| 187 | close(b.runningWaitersCh) |
| 188 | b.notifyListeners(func(l Listener) { l.Running() }, false) |
| 189 | }) |
| 190 | |
| 191 | stoppingFrom = Running |
| 192 | if b.runningFn != nil { |
| 193 | err = b.runningFn(b.serviceContext) |
| 194 | } |
| 195 | |
| 196 | stop: |
| 197 | failure := err |
| 198 | b.mustSwitchState(stoppingFrom, Stopping, func() { |
| 199 | if stoppingFrom == Starting { |
| 200 | // we will not reach Running state |
| 201 | close(b.runningWaitersCh) |
| 202 | } |
| 203 | b.notifyListeners(func(l Listener) { l.Stopping(stoppingFrom) }, false) |
| 204 | }) |
| 205 | |
| 206 | // Make sure we cancel the context before running stoppingFn |
| 207 | b.serviceCancel() |
| 208 | |
| 209 | if b.stoppingFn != nil { |
| 210 | err = b.stoppingFn(failure) |
| 211 | if failure == nil { |
| 212 | failure = err |
| 213 | } |
no test coverage detected