MCPcopy Index your code
hub / github.com/coder/code-server / Heart

Class Heart

src/node/heart.ts:8–82  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

6 * Provides a heartbeat using a local file to indicate activity.
7 */
8export class Heart {
9 private heartbeatTimer?: NodeJS.Timeout
10 private heartbeatInterval = 60000
11 public lastHeartbeat = 0
12 private readonly _onChange = new Emitter<"alive" | "expired" | "unknown">()
13 readonly onChange = this._onChange.event
14 private state: "alive" | "expired" | "unknown" = "expired"
15
16 public constructor(
17 private readonly heartbeatPath: string,
18 private readonly isActive: () => Promise<boolean>,
19 ) {
20 this.beat = this.beat.bind(this)
21 this.alive = this.alive.bind(this)
22 }
23
24 private setState(state: typeof this.state) {
25 if (this.state !== state) {
26 this.state = state
27 this._onChange.emit(this.state)
28 }
29 }
30
31 public alive(): boolean {
32 const now = Date.now()
33 return now - this.lastHeartbeat < this.heartbeatInterval
34 }
35 /**
36 * Write to the heartbeat file if we haven't already done so within the
37 * timeout and start or reset a timer that keeps running as long as there is
38 * activity. Failures are logged as warnings.
39 */
40 public async beat(): Promise<void> {
41 if (this.alive()) {
42 this.setState("alive")
43 return
44 }
45
46 logger.debug("heartbeat")
47 this.lastHeartbeat = Date.now()
48 if (typeof this.heartbeatTimer !== "undefined") {
49 clearTimeout(this.heartbeatTimer)
50 }
51
52 this.heartbeatTimer = setTimeout(async () => {
53 try {
54 if (await this.isActive()) {
55 this.beat()
56 } else {
57 this.setState("expired")
58 }
59 } catch (error: unknown) {
60 logger.warn((error as Error).message)
61 this.setState("unknown")
62 }
63 }, this.heartbeatInterval)
64
65 this.setState("alive")

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected