Skip to content

Commit

Permalink
Add support for offline db migration (#16566)
Browse files Browse the repository at this point in the history
  • Loading branch information
bramkragten authored and piitaya committed May 23, 2023
1 parent e8eddfb commit 3af02d8
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 7 deletions.
14 changes: 14 additions & 0 deletions src/data/recorder.ts
Expand Up @@ -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 {
Expand Down Expand Up @@ -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"
Expand Down
17 changes: 12 additions & 5 deletions src/layouts/ha-init-page.ts
Expand Up @@ -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
Expand All @@ -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>
`;
}

Expand All @@ -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();
Expand Down Expand Up @@ -96,6 +102,7 @@ class HaInitPage extends LitElement {
#loading-text {
max-width: 350px;
color: var(--primary-text-color);
text-align: center;
}
`;
}
Expand Down
48 changes: 46 additions & 2 deletions src/layouts/home-assistant.ts
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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>`
);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/state/connection-mixin.ts
Expand Up @@ -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();
});
}

Expand Down
4 changes: 4 additions & 0 deletions src/state/hass-base-mixin.ts
Expand Up @@ -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;
Expand Down

0 comments on commit 3af02d8

Please sign in to comment.