From 54ee1e1cf3493789ca169c5a5bd9e32f0b0cec91 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Mon, 14 Apr 2025 16:58:17 +0100 Subject: [PATCH] fix: Improve reliability of connection cleanup (#2009) - Closes #1992 --- src/components/elements.ts | 1 + src/components/live/provider.ts | 1 + src/components/live/providers/go2rtc/index.ts | 1 + src/components/surround-basic.ts | 2 +- src/components/thumbnail.ts | 4 ++-- src/components/zoomer.ts | 1 + src/patches/ha-web-rtc-player.ts | 18 ++++++++++++++++++ 7 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/components/elements.ts b/src/components/elements.ts index 80e69dab..ecf2b222 100644 --- a/src/components/elements.ts +++ b/src/components/elements.ts @@ -301,6 +301,7 @@ export class AdvancedCameraCardElementsConditional extends LitElement { disconnectedCallback(): void { this._conditionManager?.destroy(); + super.disconnectedCallback(); } protected _createConditionManager(): void { diff --git a/src/components/live/provider.ts b/src/components/live/provider.ts index 24d81e31..9b958139 100644 --- a/src/components/live/provider.ts +++ b/src/components/live/provider.ts @@ -128,6 +128,7 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP public disconnectedCallback(): void { this._isVideoMediaLoaded = false; + super.disconnectedCallback(); } protected _videoMediaShowHandler(): void { diff --git a/src/components/live/providers/go2rtc/index.ts b/src/components/live/providers/go2rtc/index.ts index 7d5d6c3c..ea59502f 100644 --- a/src/components/live/providers/go2rtc/index.ts +++ b/src/components/live/providers/go2rtc/index.ts @@ -68,6 +68,7 @@ export class AdvancedCameraCardGo2RTC extends LitElement implements MediaPlayer disconnectedCallback(): void { this._player = undefined; this._message = null; + super.disconnectedCallback(); } connectedCallback(): void { diff --git a/src/components/surround-basic.ts b/src/components/surround-basic.ts index 9a58d2fc..41b5a87f 100644 --- a/src/components/surround-basic.ts +++ b/src/components/surround-basic.ts @@ -30,7 +30,6 @@ export class AdvancedCameraCardSurroundBasic extends LitElement { } disconnectedCallback(): void { - super.disconnectedCallback(); this.removeEventListener( 'advanced-camera-card:drawer:open', this._boundDrawerHandler, @@ -39,6 +38,7 @@ export class AdvancedCameraCardSurroundBasic extends LitElement { 'advanced-camera-card:drawer:close', this._boundDrawerHandler, ); + super.disconnectedCallback(); } protected _drawerHandler(ev: Event) { diff --git a/src/components/thumbnail.ts b/src/components/thumbnail.ts index 00e66ee7..da936575 100644 --- a/src/components/thumbnail.ts +++ b/src/components/thumbnail.ts @@ -64,16 +64,16 @@ export class AdvancedCameraCardThumbnailFeatureThumbnail extends LitElement { * Component connected callback. */ connectedCallback(): void { - this._intersectionObserver.observe(this); super.connectedCallback(); + this._intersectionObserver.observe(this); } /** * Component disconnected callback. */ disconnectedCallback(): void { - super.disconnectedCallback(); this._intersectionObserver.disconnect(); + super.disconnectedCallback(); } protected willUpdate(changedProps: PropertyValues): void { diff --git a/src/components/zoomer.ts b/src/components/zoomer.ts index 3cccab2a..1c7f5190 100644 --- a/src/components/zoomer.ts +++ b/src/components/zoomer.ts @@ -40,6 +40,7 @@ export class AdvancedCameraCardZoomer extends LitElement { this._zoom?.deactivate(); this.removeEventListener('advanced-camera-card:zoom:zoomed', this._zoomHandler); this.removeEventListener('advanced-camera-card:zoom:unzoomed', this._unzoomHandler); + super.disconnectedCallback(); } protected willUpdate(changedProps: PropertyValues): void { diff --git a/src/patches/ha-web-rtc-player.ts b/src/patches/ha-web-rtc-player.ts index c73099a6..8b42fdb3 100644 --- a/src/patches/ha-web-rtc-player.ts +++ b/src/patches/ha-web-rtc-player.ts @@ -54,6 +54,24 @@ customElements.whenDefined('ha-web-rtc-player').then(() => { return this._mediaPlayerController; } + private async _startWebRtc(): Promise { + // There is a race condition in the underlying HA frontend code between + // the element connection and the async start of the WebRTC session. If + // the element is rapidly connected and disconnected, the RTC connection + // may be left permanently "dangling" causing leaks. To reproduce (without + // this workaround), watch the number of open connections on the go2rtc + // UI, then edit and rapidly save a dashboard with this card -- the number + // of open connections will not return to 1. + // See: https://github.com/dermotduffy/advanced-camera-card/issues/1992 + await super._startWebRtc(); + + // Workaround: After attempting to start a WebRTC session, check if the + // element is connected and if not then clean up correctly. + if (!this.isConnected) { + this._cleanUp(); + } + } + // ===================================================================================== // Minor modifications from: // - https://github.com/home-assistant/frontend/blob/dev/src/components/ha-web-rtc-player.ts