Files
XCDesktop/api/modules/time-tracking/heartbeatService.ts
2026-03-08 01:34:54 +08:00

81 lines
1.7 KiB
TypeScript

import { logger } from '../../utils/logger.js'
export interface HeartbeatCallback {
(): Promise<void>
}
export interface HeartbeatState {
lastHeartbeat: Date
isRunning: boolean
}
const DEFAULT_HEARTBEAT_INTERVAL = 60000
export class HeartbeatService {
private interval: NodeJS.Timeout | null = null
private lastHeartbeat: Date = new Date()
private readonly intervalMs: number
private callback: HeartbeatCallback | null = null
constructor(intervalMs: number = DEFAULT_HEARTBEAT_INTERVAL) {
this.intervalMs = intervalMs
}
setCallback(callback: HeartbeatCallback): void {
this.callback = callback
}
start(): void {
if (this.interval) {
this.stop()
}
this.interval = setInterval(async () => {
if (this.callback) {
try {
this.lastHeartbeat = new Date()
await this.callback()
} catch (err) {
logger.error('Heartbeat callback failed:', err)
}
}
}, this.intervalMs)
this.lastHeartbeat = new Date()
}
stop(): void {
if (this.interval) {
clearInterval(this.interval)
this.interval = null
}
}
isRunning(): boolean {
return this.interval !== null
}
getLastHeartbeat(): Date {
return this.lastHeartbeat
}
updateHeartbeat(): void {
this.lastHeartbeat = new Date()
}
getState(): HeartbeatState {
return {
lastHeartbeat: this.lastHeartbeat,
isRunning: this.isRunning()
}
}
restoreState(state: { lastHeartbeat: string }): void {
this.lastHeartbeat = new Date(state.lastHeartbeat)
}
}
export const createHeartbeatService = (intervalMs?: number): HeartbeatService => {
return new HeartbeatService(intervalMs)
}