-
Notifications
You must be signed in to change notification settings - Fork 5.9k
/
Copy pathheart.ts
72 lines (66 loc) · 1.84 KB
/
heart.ts
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { logger } from "@coder/logger"
import { promises as fs } from "fs"
/**
* Provides a heartbeat using a local file to indicate activity.
*/
export class Heart {
private heartbeatTimer?: NodeJS.Timeout
private heartbeatInterval = 60000
public lastHeartbeat = 0
public constructor(
private readonly heartbeatPath: string,
private readonly isActive: () => Promise<boolean>,
) {
this.beat = this.beat.bind(this)
this.alive = this.alive.bind(this)
}
public alive(): boolean {
const now = Date.now()
return now - this.lastHeartbeat < this.heartbeatInterval
}
/**
* Write to the heartbeat file if we haven't already done so within the
* timeout and start or reset a timer that keeps running as long as there is
* activity. Failures are logged as warnings.
*/
public async beat(): Promise<void> {
if (this.alive()) {
return
}
logger.debug("heartbeat")
this.lastHeartbeat = Date.now()
if (typeof this.heartbeatTimer !== "undefined") {
clearTimeout(this.heartbeatTimer)
}
this.heartbeatTimer = setTimeout(() => heartbeatTimer(this.isActive, this.beat), this.heartbeatInterval)
try {
return await fs.writeFile(this.heartbeatPath, "")
} catch (error: any) {
logger.warn(error.message)
}
}
/**
* Call to clear any heartbeatTimer for shutdown.
*/
public dispose(): void {
if (typeof this.heartbeatTimer !== "undefined") {
clearTimeout(this.heartbeatTimer)
}
}
}
/**
* Helper function for the heartbeatTimer.
*
* If heartbeat is active, call beat. Otherwise do nothing.
*
* Extracted to make it easier to test.
*/
export async function heartbeatTimer(isActive: Heart["isActive"], beat: Heart["beat"]) {
try {
if (await isActive()) {
beat()
}
} catch (error: unknown) {
logger.warn((error as Error).message)
}
}