@@ -6,6 +6,7 @@ import { promises as fs } from "fs"
6
6
*/
7
7
export class Heart {
8
8
private heartbeatTimer ?: NodeJS . Timeout
9
+ private idleCheckTimer ?: NodeJS . Timeout
9
10
private heartbeatInterval = 60000
10
11
public lastHeartbeat = 0
11
12
@@ -16,6 +17,10 @@ export class Heart {
16
17
) {
17
18
this . beat = this . beat . bind ( this )
18
19
this . alive = this . alive . bind ( this )
20
+ // Start idle check timer if timeout is configured
21
+ if ( this . idleTimeout ) {
22
+ this . startIdleCheck ( )
23
+ }
19
24
}
20
25
21
26
public alive ( ) : boolean {
@@ -37,24 +42,35 @@ export class Heart {
37
42
if ( typeof this . heartbeatTimer !== "undefined" ) {
38
43
clearTimeout ( this . heartbeatTimer )
39
44
}
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 )
44
46
try {
45
47
return await fs . writeFile ( this . heartbeatPath , "" )
46
48
} catch ( error : any ) {
47
49
logger . warn ( error . message )
48
50
}
49
51
}
50
52
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
+
51
64
/**
52
65
* Call to clear any heartbeatTimer for shutdown.
53
66
*/
54
67
public dispose ( ) : void {
55
68
if ( typeof this . heartbeatTimer !== "undefined" ) {
56
69
clearTimeout ( this . heartbeatTimer )
57
70
}
71
+ if ( typeof this . idleCheckTimer !== "undefined" ) {
72
+ clearInterval ( this . idleCheckTimer )
73
+ }
58
74
}
59
75
}
60
76
@@ -65,21 +81,8 @@ export class Heart {
65
81
*
66
82
* Extracted to make it easier to test.
67
83
*/
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" ] ) {
74
85
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
- }
83
86
if ( await isActive ( ) ) {
84
87
beat ( )
85
88
}
0 commit comments