diff --git a/packages/mds-jurisdiction-service/client/index.ts b/packages/mds-jurisdiction-service/client/index.ts index d4d615ca8..d94dcb0f3 100644 --- a/packages/mds-jurisdiction-service/client/index.ts +++ b/packages/mds-jurisdiction-service/client/index.ts @@ -18,7 +18,7 @@ import { UnwrapServiceResult, ServiceClient } from '@mds-core/mds-service-helper import { JurisdictionServiceProvider } from '../service/provider' import { JurisdictionService } from '../@types' -const { initialize, shutdown, ...service } = JurisdictionServiceProvider +const { start, stop, ...service } = JurisdictionServiceProvider export const JurisdictionServiceClient: ServiceClient = { createJurisdiction: UnwrapServiceResult(service.createJurisdiction), diff --git a/packages/mds-jurisdiction-service/server/index.ts b/packages/mds-jurisdiction-service/server/index.ts index 82958d87d..b67d64836 100644 --- a/packages/mds-jurisdiction-service/server/index.ts +++ b/packages/mds-jurisdiction-service/server/index.ts @@ -14,7 +14,7 @@ limitations under the License. */ -import { ServiceManager } from '@mds-core/mds-service-helpers' +import { ProcessManager } from '@mds-core/mds-service-helpers' import { JurisdictionServiceProvider } from '../service/provider' -ServiceManager.run(JurisdictionServiceProvider) +ProcessManager(JurisdictionServiceProvider).monitor() diff --git a/packages/mds-jurisdiction-service/service/provider.ts b/packages/mds-jurisdiction-service/service/provider.ts index d89119b8d..e03daf36d 100644 --- a/packages/mds-jurisdiction-service/service/provider.ts +++ b/packages/mds-jurisdiction-service/service/provider.ts @@ -14,13 +14,13 @@ limitations under the License. */ -import { ServiceProvider } from '@mds-core/mds-service-helpers' +import { ServiceProvider, ProcessController } from '@mds-core/mds-service-helpers' import { JurisdictionRepository } from './repository' import { JurisdictionService } from '../@types' import * as handlers from './handlers' -export const JurisdictionServiceProvider: ServiceProvider = { - initialize: JurisdictionRepository.initialize, - shutdown: JurisdictionRepository.shutdown, +export const JurisdictionServiceProvider: ServiceProvider & ProcessController = { + start: JurisdictionRepository.initialize, + stop: JurisdictionRepository.shutdown, ...handlers } diff --git a/packages/mds-jurisdiction-service/tests/index.spec.ts b/packages/mds-jurisdiction-service/tests/index.spec.ts index 45b3f7a3e..1ec924548 100644 --- a/packages/mds-jurisdiction-service/tests/index.spec.ts +++ b/packages/mds-jurisdiction-service/tests/index.spec.ts @@ -16,6 +16,7 @@ import test from 'unit.js' import { uuid, days } from '@mds-core/mds-utils' +import { ProcessManager } from '@mds-core/mds-service-helpers' import { JurisdictionServiceClient } from '../index' import { JurisdictionServiceProvider } from '../service/provider' @@ -26,9 +27,11 @@ const TODAY = Date.now() const YESTERDAY = TODAY - days(1) const LAST_WEEK = TODAY - days(7) +const controller = ProcessManager(JurisdictionServiceProvider).controller() + describe('Write/Read Jurisdictions', () => { before(async () => { - await JurisdictionServiceProvider.initialize() + await controller.start() }) it(`Write ${records} Jurisdiction${records > 1 ? 's' : ''}`, async () => { @@ -228,6 +231,6 @@ describe('Write/Read Jurisdictions', () => { }) after(async () => { - await JurisdictionServiceProvider.shutdown() + await controller.stop() }) }) diff --git a/packages/mds-jurisdiction/tests/api.spec.ts b/packages/mds-jurisdiction/tests/api.spec.ts index 978feb792..ff436cadb 100644 --- a/packages/mds-jurisdiction/tests/api.spec.ts +++ b/packages/mds-jurisdiction/tests/api.spec.ts @@ -21,7 +21,7 @@ import { uuid } from '@mds-core/mds-utils' import { JurisdictionServiceProvider } from '@mds-core/mds-jurisdiction-service/service/provider' import { SCOPED_AUTH } from '@mds-core/mds-test-data' import { JurisdictionDomainModel } from '@mds-core/mds-jurisdiction-service' -import { ServiceManager } from '@mds-core/mds-service-helpers' +import { ProcessManager } from '@mds-core/mds-service-helpers' import { api } from '../api' import { JURISDICTION_API_DEFAULT_VERSION } from '../@types' @@ -34,11 +34,11 @@ const [JURISDICTION0, JURISDICTION1, JURISDICTION2] = [uuid(), uuid(), uuid()].m geography_id: uuid() })) -const service = ServiceManager.controller(JurisdictionServiceProvider) +const controller = ProcessManager(JurisdictionServiceProvider).controller() describe('Test Jurisdiction API', () => { before(async () => { - await service.start() + await controller.start() }) it('Create Single Jurisdiction', async () => { @@ -214,6 +214,6 @@ describe('Test Jurisdiction API', () => { }) after(async () => { - await service.stop() + await controller.stop() }) }) diff --git a/packages/mds-service-helpers/@types/index.ts b/packages/mds-service-helpers/@types/index.ts index a86c12e9d..321b0488a 100644 --- a/packages/mds-service-helpers/@types/index.ts +++ b/packages/mds-service-helpers/@types/index.ts @@ -49,7 +49,9 @@ export type ServiceClient = { export type ServiceProvider = { [P in keyof I]: I[P] extends AnyFunction ? (...args: Parameters) => Promise> : never -} & { - initialize: () => Promise - shutdown: () => Promise +} + +export interface ProcessController { + start: () => Promise + stop: () => Promise } diff --git a/packages/mds-service-helpers/server/index.ts b/packages/mds-service-helpers/server/index.ts index 14c4048c5..b80bfb048 100644 --- a/packages/mds-service-helpers/server/index.ts +++ b/packages/mds-service-helpers/server/index.ts @@ -18,7 +18,7 @@ import logger from '@mds-core/mds-logger' import { hours, minutes, seconds, NotFoundError, ValidationError, ConflictError } from '@mds-core/mds-utils' import { Nullable } from '@mds-core/mds-types' import retry, { Options as RetryOptions } from 'async-retry' -import { ServiceProvider, ServiceResultType, ServiceErrorDescriptor, ServiceErrorType } from '../@types' +import { ServiceResultType, ServiceErrorDescriptor, ServiceErrorType, ProcessController } from '../@types' type ProcessMonitorOptions = Partial< Omit & { @@ -27,14 +27,10 @@ type ProcessMonitorOptions = Partial< } > -type ProcessMonitor = { - stop: () => Promise -} - -const ServiceMonitor = async ( - service: ServiceProvider, +const ProcessMonitor = async ( + controller: ProcessController, options: ProcessMonitorOptions = {} -): Promise => { +): Promise => { const { interval = hours(1), signals = ['SIGINT', 'SIGTERM'], @@ -54,8 +50,8 @@ const ServiceMonitor = async ( try { await retry( async () => { - logger.info(`Initializing service ${version}`) - await service.initialize() + logger.info(`Initializing process ${version}`) + await controller.start() }, { retries, @@ -66,51 +62,55 @@ const ServiceMonitor = async ( onRetry: (error, attempt) => { /* istanbul ignore next */ logger.error( - `Initializing service ${version} failed: ${error.message}, Retrying ${attempt} of ${retries}....` + `Initializing process ${version} failed: ${error.message}, Retrying ${attempt} of ${retries}....` ) } } ) } catch (error) /* istanbul ignore next */ { - logger.error(`Initializing service ${version} failed: ${error.message}, Exiting...`) - await service.shutdown() + logger.error(`Initializing process ${version} failed: ${error.message}, Exiting...`) + await controller.stop() process.exit(1) } // Keep NodeJS process alive - logger.info(`Monitoring service ${version} for ${signals.join(', ')}`) + logger.info(`Monitoring process ${version} for ${signals.join(', ')}`) const timeout = setInterval(() => { - logger.info(`Monitoring service ${version} for ${signals.join(', ')}`) + logger.info(`Monitoring process ${version} for ${signals.join(', ')}`) }, interval) - const shutdown = async (signal: NodeJS.Signals) => { + const terminate = async (signal: NodeJS.Signals) => { clearInterval(timeout) - logger.info(`Terminating service ${version} on ${signal}`) - await service.shutdown() + logger.info(`Terminating process ${version} on ${signal}`) + await controller.stop() process.exit(0) } // Monitor process for signals signals.forEach(signal => process.on(signal, async () => { - await shutdown(signal) + await terminate(signal) }) ) - return { stop: async () => shutdown('SIGUSR1') } + return { + start: async () => undefined, + stop: async () => terminate('SIGUSR1') + } } -export const ServiceManager = { - run: (service: ServiceProvider, options: ProcessMonitorOptions = {}) => { +export const ProcessManager = (controller: ProcessController, options: ProcessMonitorOptions = {}) => ({ + monitor: () => { + // eslint-reason disable in this one location until top-level await // eslint-disable-next-line @typescript-eslint/no-floating-promises - ServiceMonitor(service, options) + ProcessMonitor(controller, options) }, - controller: (service: ServiceProvider, options: ProcessMonitorOptions = {}) => { - let monitor: Nullable = null + controller: (): ProcessController => { + let monitor: Nullable = null return { start: async () => { if (!monitor) { - monitor = await ServiceMonitor(service, options) + monitor = await ProcessMonitor(controller, options) } }, stop: async () => { @@ -121,7 +121,7 @@ export const ServiceManager = { } } } -} +}) export const ServiceResult = (result: R): ServiceResultType => ({ error: null, result }) diff --git a/packages/mds-service-helpers/tests/index.spec.ts b/packages/mds-service-helpers/tests/index.spec.ts index 5a0d9bf48..9e2cb0bb8 100644 --- a/packages/mds-service-helpers/tests/index.spec.ts +++ b/packages/mds-service-helpers/tests/index.spec.ts @@ -15,7 +15,7 @@ */ import test from 'unit.js' -import { ServiceResult, ServiceError, ServiceException, isServiceError, ServiceManager } from '../index' +import { ServiceResult, ServiceError, ServiceException, isServiceError, ProcessManager } from '../index' import { UnwrapServiceResult } from '../client' describe('Tests Service Helpers', () => { @@ -88,14 +88,14 @@ describe('Tests Service Helpers', () => { it('Test ServiceManager Controller', async () => { let started = false - const controller = ServiceManager.controller({ - initialize: async () => { + const controller = ProcessManager({ + start: async () => { started = true }, - shutdown: async () => { + stop: async () => { started = false } - }) + }).controller() await controller.start() test.value(started).is(true) await controller.stop()