()
| 662 | // - result write: fire-and-forget, archive latency covers the drain |
| 663 | // - 401 retry: only if first archive 401s, shares the same budget |
| 664 | async function teardown(): Promise<void> { |
| 665 | if (tornDown) return |
| 666 | tornDown = true |
| 667 | refresh.cancelAll() |
| 668 | clearTimeout(connectDeadline) |
| 669 | flushGate.drop() |
| 670 | |
| 671 | // Fire the result message before archive — transport.write() only awaits |
| 672 | // enqueue (SerialBatchEventUploader resolves once buffered, drain is |
| 673 | // async). Archiving before close() gives the uploader's drain loop a |
| 674 | // window (typical archive ≈ 100-500ms) to POST the result without an |
| 675 | // explicit sleep. close() sets closed=true which interrupts drain at the |
| 676 | // next while-check, so close-before-archive drops the result. |
| 677 | transport.reportState('idle') |
| 678 | void transport.write(makeResultMessage(sessionId)) |
| 679 | |
| 680 | let token = getAccessToken() |
| 681 | let status = await archiveSession( |
| 682 | sessionId, |
| 683 | baseUrl, |
| 684 | token, |
| 685 | orgUUID, |
| 686 | cfg.teardown_archive_timeout_ms, |
| 687 | ) |
| 688 | |
| 689 | // Token is usually fresh (refresh scheduler runs 5min before expiry) but |
| 690 | // laptop-wake past the refresh window leaves getAccessToken() returning a |
| 691 | // stale string. Retry once on 401 — onAuth401 (= handleOAuth401Error) |
| 692 | // clears keychain cache + force-refreshes. No proactive refresh on the |
| 693 | // happy path: handleOAuth401Error force-refreshes even valid tokens, |
| 694 | // which would waste budget 99% of the time. try/catch mirrors |
| 695 | // recoverFromAuthFailure: keychain reads can throw (macOS locked after |
| 696 | // wake); an uncaught throw here would skip transport.close + telemetry. |
| 697 | if (status === 401 && onAuth401) { |
| 698 | try { |
| 699 | await onAuth401(token ?? '') |
| 700 | token = getAccessToken() |
| 701 | status = await archiveSession( |
| 702 | sessionId, |
| 703 | baseUrl, |
| 704 | token, |
| 705 | orgUUID, |
| 706 | cfg.teardown_archive_timeout_ms, |
| 707 | ) |
| 708 | } catch (err) { |
| 709 | logForDebugging( |
| 710 | `[remote-bridge] Teardown 401 retry threw: ${errorMessage(err)}`, |
| 711 | { level: 'error' }, |
| 712 | ) |
| 713 | } |
| 714 | } |
| 715 | |
| 716 | transport.close() |
| 717 | |
| 718 | const archiveStatus: ArchiveTelemetryStatus = |
| 719 | status === 'no_token' |
| 720 | ? 'skipped_no_token' |
| 721 | : status === 'timeout' || status === 'error' |
nothing calls this directly
no test coverage detected