summaryrefslogtreecommitdiff
path: root/lib/process/signals.ts
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-07-27 17:03:10 -0700
committerElizabeth Hunt <me@liz.coffee>2025-07-27 18:30:30 -0700
commit9970036d203ba2d0a46b35ba6fad21d49441cdd4 (patch)
treea585d13933bf4149dcb07e28526063d071453105 /lib/process/signals.ts
downloadpengueno-9970036d203ba2d0a46b35ba6fad21d49441cdd4.tar.gz
pengueno-9970036d203ba2d0a46b35ba6fad21d49441cdd4.zip
hai
Diffstat (limited to 'lib/process/signals.ts')
-rw-r--r--lib/process/signals.ts49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/process/signals.ts b/lib/process/signals.ts
new file mode 100644
index 0000000..c4feb7a
--- /dev/null
+++ b/lib/process/signals.ts
@@ -0,0 +1,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));
+ });
+ }
+}