in common/lib/plugins/efm/monitor.ts [117:225]
async run(): Promise<void> {
logger.debug(Messages.get("MonitorImpl.startMonitoring", this.hostInfo.host));
try {
while (!this.cancelled) {
try {
let newMonitorContext: MonitorConnectionContext | undefined;
let firstAddedNewMonitorContext: MonitorConnectionContext | null = null;
const currentTimeNano: number = getCurrentTimeNano();
while ((newMonitorContext = this.newContexts?.shift()) != null) {
if (firstAddedNewMonitorContext === newMonitorContext) {
this.newContexts.push(newMonitorContext);
break;
}
if (newMonitorContext.isActiveContext) {
if (newMonitorContext.expectedActiveMonitoringStartTimeNano > currentTimeNano) {
this.newContexts.push(newMonitorContext);
firstAddedNewMonitorContext = firstAddedNewMonitorContext ?? newMonitorContext;
} else {
this.activeContexts.push(newMonitorContext);
}
}
}
if (this.activeContexts.length > 0) {
this.contextLastUsedTimestampNanos = getCurrentTimeNano();
const statusCheckStartTimeNanos: number = getCurrentTimeNano();
this.contextLastUsedTimestampNanos = statusCheckStartTimeNanos;
const status: ConnectionStatus = await this.checkConnectionStatus();
let delayMillis: number = -1;
let monitorContext: MonitorConnectionContext | undefined;
let firstAddedMonitorContext: MonitorConnectionContext | null = null;
while ((monitorContext = this.activeContexts?.shift()) != null) {
// If context is already invalid, just skip it.
if (!monitorContext.isActiveContext) {
continue;
}
if (firstAddedMonitorContext == monitorContext) {
// This context is already processed by this loop.
// Add it to the array and exit this loop.
this.activeContexts?.push(monitorContext);
break;
}
// Otherwise, process this context.
await monitorContext.updateConnectionStatus(
this.hostInfo.url,
statusCheckStartTimeNanos,
statusCheckStartTimeNanos + status.elapsedTimeNano,
status.isValid
);
if (monitorContext.isActiveContext && !monitorContext.isHostUnhealthy) {
this.activeContexts?.push(monitorContext);
if (firstAddedMonitorContext == null) {
firstAddedMonitorContext = monitorContext;
}
if (delayMillis === -1 || delayMillis > monitorContext.failureDetectionIntervalMillis) {
delayMillis = monitorContext.failureDetectionIntervalMillis;
}
}
}
if (delayMillis === -1) {
// No active contexts.
delayMillis = this.SLEEP_WHEN_INACTIVE_MILLIS;
} else {
delayMillis -= Math.round(status.elapsedTimeNano / 1_000_000);
// Check for minimum delay between host health check;
if (delayMillis <= 0) {
delayMillis = this.MIN_CONNECTION_CHECK_TIMEOUT_MILLIS;
}
}
await new Promise((resolve) => {
this.delayMillisTimeoutId = setTimeout(resolve, delayMillis);
});
} else {
if (getCurrentTimeNano() - this.contextLastUsedTimestampNanos >= this.monitorDisposalTimeMillis * 1_000_000) {
break;
}
await new Promise((resolve) => {
this.sleepWhenInactiveTimeoutId = setTimeout(resolve, this.SLEEP_WHEN_INACTIVE_MILLIS);
});
}
} catch (error: any) {
logger.debug(Messages.get("MonitorImpl.errorDuringMonitoringContinue", error.message));
}
}
} catch (error: any) {
logger.debug(Messages.get("MonitorImpl.errorDuringMonitoringStop", error.message));
} finally {
this.stopped = true;
await this.endMonitoringClient();
}
logger.debug(Messages.get("MonitorImpl.stopMonitoring", this.hostInfo.host));
}