Add support for offline db migration (#16566)

This commit is contained in:
Bram Kragten 2023-05-22 10:39:06 +02:00 committed by GitHub
parent 330aa23801
commit 34e59e543b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 7 deletions

View File

@ -2,6 +2,15 @@ import { computeStateName } from "../common/entity/compute_state_name";
import { HaDurationData } from "../components/ha-duration-input";
import { HomeAssistant } from "../types";
export interface RecorderInfo {
backlog: number | null;
max_backlog: number;
migration_in_progress: boolean;
migration_is_live: boolean;
recording: boolean;
thread_running: boolean;
}
export type StatisticType = "change" | "state" | "sum" | "min" | "max" | "mean";
export interface Statistics {
@ -106,6 +115,11 @@ export interface StatisticsValidationResults {
[statisticId: string]: StatisticsValidationResult[];
}
export const getRecorderInfo = (hass: HomeAssistant) =>
hass.callWS<RecorderInfo>({
type: "recorder/info",
});
export const getStatisticIds = (
hass: HomeAssistant,
statistic_type?: "mean" | "sum"

View File

@ -4,11 +4,13 @@ import { property, state } from "lit/decorators";
class HaInitPage extends LitElement {
@property({ type: Boolean }) public error = false;
@property({ type: Boolean }) public migration = false;
@state() private _retryInSeconds = 60;
private _showProgressIndicatorTimeout?: NodeJS.Timeout;
private _showProgressIndicatorTimeout?: number;
private _retryInterval?: NodeJS.Timeout;
private _retryInterval?: number;
protected render() {
return this.error
@ -35,7 +37,11 @@ class HaInitPage extends LitElement {
<div id="progress-indicator-wrapper">
<ha-circular-progress active></ha-circular-progress>
</div>
<div id="loading-text">Loading data</div>
<div id="loading-text">
${this.migration
? "Database migration in progress, please wait this might take some time"
: "Loading data"}
</div>
`;
}
@ -56,11 +62,11 @@ class HaInitPage extends LitElement {
}
protected firstUpdated() {
this._showProgressIndicatorTimeout = setTimeout(() => {
this._showProgressIndicatorTimeout = window.setTimeout(() => {
import("../components/ha-circular-progress");
}, 5000);
this._retryInterval = setInterval(() => {
this._retryInterval = window.setInterval(() => {
const remainingSeconds = this._retryInSeconds--;
if (remainingSeconds <= 0) {
this._retry();
@ -96,6 +102,7 @@ class HaInitPage extends LitElement {
#loading-text {
max-width: 350px;
color: var(--primary-text-color);
text-align: center;
}
`;
}

View File

@ -3,6 +3,7 @@ import { customElement, state } from "lit/decorators";
import { isNavigationClick } from "../common/dom/is-navigation-click";
import { navigate } from "../common/navigate";
import { getStorageDefaultPanelUrlPath } from "../data/panel";
import { getRecorderInfo } from "../data/recorder";
import "../resources/custom-card-support";
import { HassElement } from "../state/hass-element";
import QuickBarMixin from "../state/quick-bar-mixin";
@ -32,6 +33,8 @@ const panelUrl = (path: string) => {
export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
@state() private _route: Route;
@state() private _databaseMigration?: boolean;
private _panelUrl: string;
private _haVersion?: string;
@ -65,8 +68,24 @@ export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
`;
}
willUpdate(changedProps: PropertyValues<this>) {
if (
this._databaseMigration === undefined &&
changedProps.has("hass") &&
this.hass?.config &&
changedProps.get("hass")?.config !== this.hass?.config
) {
this.checkDataBaseMigration();
}
}
update(changedProps: PropertyValues<this>) {
if (this.hass?.states && this.hass.config && this.hass.services) {
if (
this.hass?.states &&
this.hass.config &&
this.hass.services &&
this._databaseMigration === false
) {
this.render = this.renderHass;
this.update = super.update;
removeLaunchScreen();
@ -131,6 +150,14 @@ export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
changedProps.get("hass") as HomeAssistant | undefined
);
}
if (changedProps.has("_databaseMigration")) {
if (this.render !== this.renderHass) {
this._renderInitInfo(false);
} else if (this._databaseMigration) {
// we already removed the launch screen, so we refresh to add it again to show the migration screen
location.reload();
}
}
}
protected hassConnected() {
@ -174,6 +201,20 @@ export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
}
}
protected async checkDataBaseMigration() {
if (this.hass?.config?.components.includes("recorder")) {
const info = await getRecorderInfo(this.hass);
this._databaseMigration =
info.migration_in_progress && !info.migration_is_live;
if (this._databaseMigration) {
// check every 5 seconds if the migration is done
setTimeout(() => this.checkDataBaseMigration(), 5000);
}
} else {
this._databaseMigration = false;
}
}
protected async _initializeHass() {
try {
let result;
@ -250,7 +291,10 @@ export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
private _renderInitInfo(error: boolean) {
renderLaunchScreenInfoBox(
html`<ha-init-page .error=${error}></ha-init-page>`
html`<ha-init-page
.error=${error}
.migration=${this._databaseMigration}
></ha-init-page>`
);
}
}

View File

@ -249,6 +249,7 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
// @ts-ignore
this.hass!.callWS({ type: "get_config" }).then((config: HassConfig) => {
this._updateHass({ config });
this.checkDataBaseMigration();
});
}

View File

@ -38,6 +38,10 @@ export class HassBaseEl extends LitElement {
// eslint-disable-next-line
}
protected checkDataBaseMigration() {
// eslint-disable-next-line
}
protected hassChanged(hass, _oldHass) {
this.__provideHass.forEach((el) => {
(el as any).hass = hass;