()
| 390 | } |
| 391 | |
| 392 | private armIdleTimer(): void { |
| 393 | if (this.idleTimer || this.stopping) return; |
| 394 | if (this.idleTimeoutMs <= 0) return; // 0 = never idle-exit |
| 395 | this.idleTimer = setTimeout(() => { |
| 396 | this.idleTimer = null; |
| 397 | // Last-second sanity check: if a connection landed between the timer |
| 398 | // firing and now, don't exit. (setImmediate-ordering is the only way |
| 399 | // this races; cheap to defend against.) |
| 400 | if (this.clients.size > 0) { |
| 401 | this.armIdleTimer(); |
| 402 | return; |
| 403 | } |
| 404 | void this.stop('idle timeout'); |
| 405 | }, this.idleTimeoutMs); |
| 406 | // Don't keep the event loop alive just for this — the net.Server keeps the |
| 407 | // loop alive while listening, so the timer still fires; once we stop() the |
| 408 | // loop should drain naturally. |
| 409 | this.idleTimer.unref?.(); |
| 410 | } |
| 411 | |
| 412 | private disarmIdleTimer(): void { |
| 413 | if (!this.idleTimer) return; |
no test coverage detected