summaryrefslogtreecommitdiff
path: root/u/process/signals.ts
blob: c4feb7a54bb390e8e36f74cccbe47747d0d73bee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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<TFailure> {
    readonly close: SideEffect<SideEffect<TFailure | undefined>>;
}

export class Signals {
    public static async awaitClose<E extends Error>(
        t: ITraceable<Closeable<E>, LogMetricTraceSupplier>,
    ): Promise<IEither<Error, void>> {
        const success: IEither<Error, void> = Either.right(<void>undefined);
        return new Promise<IEither<Error, void>>((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<Error, void>(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));
        });
    }
}