| 71 | } |
| 72 | |
| 73 | export class MaintenanceWorker implements IRunnable { |
| 74 | private interval: NodeJS.Timeout | undefined |
| 75 | private isRunning = false |
| 76 | |
| 77 | public constructor( |
| 78 | private readonly process: NodeJS.Process, |
| 79 | private readonly paymentsService: IPaymentsService, |
| 80 | private readonly maintenanceService: IMaintenanceService, |
| 81 | private readonly settings: () => Settings, |
| 82 | private readonly nip05VerificationRepository: INip05VerificationRepository, |
| 83 | ) { |
| 84 | this.process |
| 85 | .on('SIGINT', this.onExit.bind(this)) |
| 86 | .on('SIGHUP', this.onExit.bind(this)) |
| 87 | .on('SIGTERM', this.onExit.bind(this)) |
| 88 | .on('uncaughtException', this.onError.bind(this)) |
| 89 | .on('unhandledRejection', this.onError.bind(this)) |
| 90 | } |
| 91 | |
| 92 | private async clearOldEventsSafely(): Promise<void> { |
| 93 | try { |
| 94 | await Promise.race([ |
| 95 | this.maintenanceService.clearOldEvents(), |
| 96 | delayMs(CLEAR_OLD_EVENTS_TIMEOUT_MS).then(() => { |
| 97 | throw new Error(`clearOldEvents timed out after ${CLEAR_OLD_EVENTS_TIMEOUT_MS}ms`) |
| 98 | }), |
| 99 | ]) |
| 100 | } catch (error) { |
| 101 | logger('unable to clear old events: %o', error) |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | public run(): void { |
| 106 | this.interval = setInterval(async () => { |
| 107 | if (this.isRunning) { |
| 108 | logger('skipping scheduled maintenance run because previous run is still in progress') |
| 109 | return |
| 110 | } |
| 111 | |
| 112 | this.isRunning = true |
| 113 | try { |
| 114 | await this.onSchedule() |
| 115 | } catch (error) { |
| 116 | this.onError(error as Error) |
| 117 | } finally { |
| 118 | this.isRunning = false |
| 119 | } |
| 120 | }, UPDATE_INVOICE_INTERVAL) |
| 121 | } |
| 122 | |
| 123 | private async onSchedule(): Promise<void> { |
| 124 | const currentSettings = this.settings() |
| 125 | const clearOldEventsPromise = this.clearOldEventsSafely() |
| 126 | |
| 127 | await this.processNip05Reverifications(currentSettings) |
| 128 | |
| 129 | if (!path(['payments', 'enabled'], currentSettings)) { |
| 130 | await clearOldEventsPromise |
nothing calls this directly
no outgoing calls
no test coverage detected