Commit 52b26878 authored by Will Cory's avatar Will Cory Committed by GitHub

feat(BaseServiceV2):End immediately when looping (#2731)

* end immediately when looping

* changeset

* improvements based on comments

* add logging

* add logging ect. to main loop

* stop main loop

* get rid of this.running for this.loop

* Revert "get rid of this.running for this.loop"

This reverts commit 18e6fe88c61eb154bc76418b0bf39914438d57a5.

* lower-case
Co-authored-by: default avatarWill Cory <willcory@Wills-MacBook-Pro.local>
parent 65a859de
---
'@eth-optimism/common-ts': minor
---
More gracefully shut down base service
......@@ -4,7 +4,6 @@ import Config from 'bcfg'
import * as dotenv from 'dotenv'
import { Command, Option } from 'commander'
import { ValidatorSpec, Spec, cleanEnv } from 'envalid'
import { sleep } from '@eth-optimism/core-utils'
import snakeCase from 'lodash/snakeCase'
import express, { Router } from 'express'
import prometheus, { Registry } from 'prom-client'
......@@ -62,6 +61,17 @@ export abstract class BaseServiceV2<
TMetrics extends MetricsV2,
TServiceState
> {
/**
* The timeout that controls the polling interval
* If clearTimeout(this.pollingTimeout) is called the timeout will stop
*/
private pollingTimeout: NodeJS.Timeout
/**
* The promise representing this.main
*/
private mainPromise: ReturnType<typeof this.main>
/**
* Whether or not the service will loop.
*/
......@@ -77,11 +87,6 @@ export abstract class BaseServiceV2<
*/
protected running: boolean
/**
* Whether or not the service has run to completion.
*/
protected done: boolean
/**
* Whether or not the service is currently healthy.
*/
......@@ -373,8 +378,6 @@ export abstract class BaseServiceV2<
* main function. Will also catch unhandled errors.
*/
public async run(): Promise<void> {
this.done = false
// Start the app server if not yet running.
if (!this.server) {
this.logger.info('starting app server')
......@@ -446,9 +449,11 @@ export abstract class BaseServiceV2<
if (this.loop) {
this.logger.info('starting main loop')
this.running = true
while (this.running) {
const doLoop = async () => {
try {
await this.main()
this.mainPromise = this.main()
await this.mainPromise
} catch (err) {
this.metrics.unhandledErrors.inc()
this.logger.error('caught an unhandled exception', {
......@@ -460,15 +465,14 @@ export abstract class BaseServiceV2<
// Sleep between loops if we're still running (service not stopped).
if (this.running) {
await sleep(this.loopIntervalMs)
this.pollingTimeout = setTimeout(doLoop, this.loopIntervalMs)
}
}
doLoop()
} else {
this.logger.info('running main function')
await this.main()
}
this.done = true
}
/**
......@@ -476,13 +480,13 @@ export abstract class BaseServiceV2<
* iteration is finished and will then stop looping.
*/
public async stop(): Promise<void> {
this.logger.info('stopping main loop...')
this.running = false
// Wait until the main loop has finished.
this.logger.info('stopping service, waiting for main loop to finish')
while (!this.done) {
await sleep(1000)
}
clearTimeout(this.pollingTimeout)
this.logger.info('waiting for main to complete')
// if main is in the middle of running wait for it to complete
await this.mainPromise
this.logger.info('main loop stoped.')
// Shut down the metrics server if it's running.
if (this.server) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment