@@ -6,6 +6,7 @@ import { promises as fs } from "fs"
66 */
77export class Heart {
88 private heartbeatTimer ?: NodeJS . Timeout
9+ private idleCheckTimer ?: NodeJS . Timeout
910 private heartbeatInterval = 60000
1011 public lastHeartbeat = 0
1112
@@ -16,6 +17,10 @@ export class Heart {
1617 ) {
1718 this . beat = this . beat . bind ( this )
1819 this . alive = this . alive . bind ( this )
20+ // Start idle check timer if timeout is configured
21+ if ( this . idleTimeout ) {
22+ this . startIdleCheck ( )
23+ }
1924 }
2025
2126 public alive ( ) : boolean {
@@ -37,24 +42,35 @@ export class Heart {
3742 if ( typeof this . heartbeatTimer !== "undefined" ) {
3843 clearTimeout ( this . heartbeatTimer )
3944 }
40- this . heartbeatTimer = setTimeout (
41- ( ) => heartbeatTimer ( this . isActive , this . beat , this . lastHeartbeat , this . idleTimeout ) ,
42- this . heartbeatInterval
43- )
45+ this . heartbeatTimer = setTimeout ( ( ) => heartbeatTimer ( this . isActive , this . beat ) , this . heartbeatInterval )
4446 try {
4547 return await fs . writeFile ( this . heartbeatPath , "" )
4648 } catch ( error : any ) {
4749 logger . warn ( error . message )
4850 }
4951 }
5052
53+ private startIdleCheck ( ) : void {
54+ // Check every minute if the idle timeout has been exceeded
55+ this . idleCheckTimer = setInterval ( ( ) => {
56+ const timeSinceLastBeat = Date . now ( ) - this . lastHeartbeat
57+ if ( timeSinceLastBeat > this . idleTimeout ! * 60 * 1000 ) {
58+ logger . warn ( `Idle timeout of ${ this . idleTimeout } minutes exceeded` )
59+ process . kill ( process . pid , "SIGTERM" )
60+ }
61+ } , 60000 )
62+ }
63+
5164 /**
5265 * Call to clear any heartbeatTimer for shutdown.
5366 */
5467 public dispose ( ) : void {
5568 if ( typeof this . heartbeatTimer !== "undefined" ) {
5669 clearTimeout ( this . heartbeatTimer )
5770 }
71+ if ( typeof this . idleCheckTimer !== "undefined" ) {
72+ clearInterval ( this . idleCheckTimer )
73+ }
5874 }
5975}
6076
@@ -65,21 +81,8 @@ export class Heart {
6581 *
6682 * Extracted to make it easier to test.
6783 */
68- export async function heartbeatTimer (
69- isActive : Heart [ "isActive" ] ,
70- beat : Heart [ "beat" ] ,
71- lastHeartbeat : number ,
72- idleTimeout ?: number ,
73- ) {
84+ export async function heartbeatTimer ( isActive : Heart [ "isActive" ] , beat : Heart [ "beat" ] ) {
7485 try {
75- // Check for idle timeout first
76- if ( idleTimeout ) {
77- const timeSinceLastBeat = Date . now ( ) - lastHeartbeat
78- if ( timeSinceLastBeat > idleTimeout * 60 * 1000 ) {
79- logger . warn ( `Idle timeout of ${ idleTimeout } minutes exceeded` )
80- process . exit ( 0 )
81- }
82- }
8386 if ( await isActive ( ) ) {
8487 beat ( )
8588 }
0 commit comments