Fixes #17769, #22503: Improved subscription handling (#22889)

* Fixes #17769, #22503: Improved subscription handling

Prevent multiple active subscriptions
Ensure a clean state when the component reconnects
Checking subscription status before processing

* Prettier issue resolved

* async methods referencing _unsubscribe are properly awaited

* Apply suggestions from code review

Thank you

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>

---------

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
This commit is contained in:
System Tester 2024-11-21 00:41:59 +10:00 committed by GitHub
parent 39b4e85dcd
commit b7f3e40340
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -138,7 +138,7 @@ export class HaLogbook extends LitElement {
this._throttleGetLogbookEntries.cancel();
this._updateTraceContexts.cancel();
this._updateUsers.cancel();
this._unsubscribeSetLoading();
await this._unsubscribeSetLoading();
this._liveUpdatesEnabled = true;
@ -207,16 +207,26 @@ export class HaLogbook extends LitElement {
);
}
private _unsubscribe() {
private async _unsubscribe(): Promise<void> {
if (this._subscribed) {
this._subscribed.then((unsub) => unsub?.());
try {
const unsub = await this._subscribed;
if (unsub) {
await unsub();
this._subscribed = undefined;
this._pendingStreamMessages = [];
}
} catch (err: any) {
// eslint-disable-next-line
console.error("Error unsubscribing:", err);
}
}
}
public connectedCallback() {
super.connectedCallback();
if (this.hasUpdated) {
// Ensure clean state before subscribing
this._subscribeLogbookPeriod(this._calculateLogbookPeriod());
}
}
@ -231,8 +241,8 @@ export class HaLogbook extends LitElement {
* Setting this._logbookEntries to undefined
* will put the page in a loading state.
*/
private _unsubscribeSetLoading() {
this._unsubscribe();
private async _unsubscribeSetLoading() {
await this._unsubscribe();
this._logbookEntries = undefined;
this._pendingStreamMessages = [];
}
@ -241,8 +251,8 @@ export class HaLogbook extends LitElement {
* Setting this._logbookEntries to an empty
* list will show a no results message.
*/
private _unsubscribeNoResults() {
this._unsubscribe();
private async _unsubscribeNoResults() {
await this._unsubscribe();
this._logbookEntries = [];
this._pendingStreamMessages = [];
}
@ -273,10 +283,12 @@ export class HaLogbook extends LitElement {
throw new Error("Unexpected time specified");
}
private _subscribeLogbookPeriod(logbookPeriod: LogbookTimePeriod) {
private async _subscribeLogbookPeriod(logbookPeriod: LogbookTimePeriod) {
if (this._subscribed) {
return true;
}
// Ensure any previous subscription is cleaned up
await this._unsubscribe();
this._subscribed = subscribeLogbook(
this.hass,
(streamMessage) => {
@ -304,7 +316,7 @@ export class HaLogbook extends LitElement {
this._error = undefined;
if (this._filterAlwaysEmptyResults) {
this._unsubscribeNoResults();
await this._unsubscribeNoResults();
return;
}
@ -312,7 +324,7 @@ export class HaLogbook extends LitElement {
if (logbookPeriod.startTime > logbookPeriod.now) {
// Time Travel not yet invented
this._unsubscribeNoResults();
await this._unsubscribeNoResults();
return;
}