import { Either, IEither, IMetric, ITraceable, LogMetricTrace, LogMetricTraceSupplier, Mapper, Metric, Optional, ResultMetric, SideEffect, TraceUtil, } from '@emprespresso/pengueno'; export const SigIntMetric = Metric.fromName('SigInt').asResult(); export const SigTermMetric = Metric.fromName('SigTerm').asResult(); export interface Closeable { readonly close: SideEffect>; } export class Signals { public static async awaitClose( t: ITraceable, LogMetricTraceSupplier>, ): Promise> { const success: IEither = Either.right(undefined); return new Promise>((res) => { const metricizedInterruptHandler = (metric: ResultMetric) => (err: Error | undefined) => t .flatMap(TraceUtil.withMetricTrace(metric)) .peek((_t) => _t.trace.trace('closing')) .move( Optional.from(err) .map((e) => Either.left(e)) .orSome(() => success) .get(), ) .flatMap(TraceUtil.traceResultingEither(metric)) .map((e) => res(e.get())) .peek((_t) => _t.trace.trace('finished')) .get(); const sigintCloser = metricizedInterruptHandler(SigIntMetric); const sigtermCloser = metricizedInterruptHandler(SigTermMetric); process.on('SIGINT', () => t.flatMap(TraceUtil.withTrace('SIGINT')).get().close(sigintCloser)); process.on('SIGTERM', () => t.flatMap(TraceUtil.withTrace('SIGTERM')).get().close(sigtermCloser)); }); } }