Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use DuckDB to store device states #2104

Merged
merged 32 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1876724
Save sensor data to DuckDB
Pierre-Gilles Jun 21, 2024
2c22fb0
Start migrateFromSqliteToDuckDB script
Pierre-Gilles Jun 24, 2024
5b817a4
Add DuckDB migration task
Pierre-Gilles Jun 24, 2024
821e3fe
Fix tests
Pierre-Gilles Jun 24, 2024
f93453f
Clean old agregate calculation
Pierre-Gilles Jun 28, 2024
8aeced1
Fix linting/tests
Pierre-Gilles Jun 28, 2024
36bbdec
Adding more tests + closing DB
Pierre-Gilles Jun 28, 2024
68d3c3c
Fix eslint warning
Pierre-Gilles Jun 28, 2024
24fc53f
Add test to device.destroy
Pierre-Gilles Jun 28, 2024
80d635e
Allow filtering of jobs per type
Pierre-Gilles Jun 28, 2024
aaf7bef
Add a dashboard message when migrating
Pierre-Gilles Jun 28, 2024
01b423f
Add backup/restore process Gladys Plus
Pierre-Gilles Jun 29, 2024
80ec2a2
Add en + de translation
Pierre-Gilles Jun 29, 2024
2458fe4
Fix tests
Pierre-Gilles Jun 29, 2024
0ac6174
Fix restore close db
Pierre-Gilles Jun 29, 2024
be83562
Add UI to see DuckDB migration and re-run it
Pierre-Gilles Jul 1, 2024
95ccd6b
Add translation for jobType
Pierre-Gilles Jul 1, 2024
6af8b39
Let the user purge SQLite only when duckDB is migrated
Pierre-Gilles Jul 15, 2024
38c43fb
Merge branch 'master' into duckdb
Pierre-Gilles Jul 15, 2024
b043fb9
Add libc6-compat to build deps in Dockerfile
Pierre-Gilles Aug 2, 2024
a5c93b0
Add gcompat
Pierre-Gilles Aug 2, 2024
70cdb44
Use only gcompat
Pierre-Gilles Aug 2, 2024
399c1f5
Try using Docker node slim instead of alpine
Pierre-Gilles Aug 2, 2024
98c81f0
Dashboard: Fix charts with lots of zeros (#2105)
Pierre-Gilles Aug 5, 2024
663ae01
Merge branch 'duckdb' of github.com:GladysAssistant/Gladys into duckdb
Pierre-Gilles Aug 5, 2024
19b6282
Make Docker image slimer
Pierre-Gilles Aug 5, 2024
5228cb5
Fix Gladys Plus backup download
Pierre-Gilles Aug 6, 2024
9ddcfc3
Fix old strategy restore
Pierre-Gilles Aug 6, 2024
2293a6c
Fix cast bug
Pierre-Gilles Aug 7, 2024
d64a365
Purge states should purge duckDB states + remove purge state agregate…
Pierre-Gilles Aug 8, 2024
3b84732
Purge sqlite states should not run 2 times in parallel
Pierre-Gilles Aug 10, 2024
628ccc0
Remove arm/v6 builds
Pierre-Gilles Aug 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker-dev-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
platforms:
description: 'Docker platform to build'
required: true
default: 'linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8'
default: 'linux/amd64,linux/arm/v7,linux/arm64/v8'

jobs:
build-front:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-release-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ jobs:
with:
context: .
file: ./docker/Dockerfile.buildx
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
push: true
pull: true
tags: ${{ steps.docker_meta.outputs.tags }}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
node_modules
*.db
*.duckdb
*.duckdb.wal
*.db-shm
*.db-wal
*.dbfile-shm
Expand Down
35 changes: 25 additions & 10 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ARG TARGET
ARG VERSION
ARG BUILD_DATE

FROM $TARGET/node:18-alpine
FROM ${TARGET}/node:18-slim

LABEL \
org.label-schema.build-date=$BUILD_DATE \
Expand All @@ -11,28 +11,43 @@ LABEL \
COPY qemu-* /usr/bin/

# System dependencies
RUN apk add --no-cache tzdata nmap ffmpeg sqlite openssl gzip eudev
RUN apt-get update && apt-get install -y --no-install-recommends \
tzdata \
nmap \
ffmpeg \
sqlite3 \
openssl \
gzip \
udev \
bluez \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /tmp

# Install Bluez dependencies
RUN apk add --no-cache bluez

# Install Gladys
RUN mkdir /src
WORKDIR /src
ADD . /src
COPY ./static /src/server/static
WORKDIR /src/server
RUN apk add --no-cache --virtual .build-deps make gcc g++ python3 py3-setuptools git libffi-dev linux-headers \
&& npm ci --unsafe-perm --production \
&& npm cache clean --force \
&& apk del .build-deps

# Install build dependencies and application dependencies
RUN apt-get update && apt-get install -y \
build-essential \
python3 \
python3-pip \
git \
libffi-dev \
&& npm ci --unsafe-perm --production \
&& npm cache clean --force \
&& apt-get autoremove -y build-essential python3 python3-pip git libffi-dev \
&& apt-get purge -y --auto-remove \
&& rm -rf /var/lib/apt/lists/*

ENV NODE_ENV production
ENV SERVER_PORT 80

# Export listening port
EXPOSE 80

CMD ["node", "index.js"]
CMD ["node", "index.js"]
30 changes: 19 additions & 11 deletions docker/Dockerfile.buildx
Original file line number Diff line number Diff line change
@@ -1,38 +1,46 @@
# STEP 1
# Prepare server package*.json files
FROM node:18-alpine as json-files
FROM node:18-slim as json-files
COPY ./server /json-files/server
WORKDIR /json-files/server/
RUN find . -type f \! -name "package*.json" -exec rm -r {} \;
COPY ./server/cli /json-files/server/cli
COPY ./server/utils /json-files/server/utils


# STEP 3
# Gladys Bundle
FROM node:18-alpine as gladys
FROM node:18-slim as gladys

# System dependencies
RUN apk add --no-cache \
RUN apt-get update && apt-get install -y --no-install-recommends \
tzdata \
nmap \
ffmpeg \
sqlite \
sqlite3 \
openssl \
gzip \
eudev \
bluez
udev \
bluez \
&& rm -rf /var/lib/apt/lists/*

COPY --from=json-files /json-files/server /src/server

ENV LD_LIBRARY_PATH /lib

WORKDIR /src/server

RUN apk add --no-cache --virtual .build-deps make gcc g++ python3 py3-setuptools git libffi-dev linux-headers \
&& npm ci --unsafe-perm --production \
&& npm cache clean --force \
&& apk del .build-deps
# Install build dependencies
RUN apt-get update && apt-get install -y \
build-essential \
python3 \
python3-pip \
git \
libffi-dev \
&& npm ci --unsafe-perm --production \
&& npm cache clean --force \
&& apt-get autoremove -y build-essential python3 python3-pip git libffi-dev \
&& apt-get purge -y --auto-remove \
&& rm -rf /var/lib/apt/lists/*

# Copy builded front
COPY ./static /src/server/static
Expand Down
6 changes: 0 additions & 6 deletions front/src/actions/signup/signupSetPreferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ function createActions(store) {
await state.httpClient.post(`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_STATE_HISTORY_IN_DAYS}`, {
value: state.signupSystemPreferences[SYSTEM_VARIABLE_NAMES.DEVICE_STATE_HISTORY_IN_DAYS]
});
await state.httpClient.post(
`/api/v1/variable/${SYSTEM_VARIABLE_NAMES.DEVICE_AGGREGATE_STATE_HISTORY_IN_DAYS}`,
{
value: state.signupSystemPreferences[SYSTEM_VARIABLE_NAMES.DEVICE_STATE_HISTORY_IN_DAYS]
}
);
store.setState({
signupSaveSystemPreferences: RequestStatus.Success
});
Expand Down
9 changes: 8 additions & 1 deletion front/src/components/boxs/chart/ApexChartAreaOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,14 @@
},
yaxis: {
labels: {
padding: 4
padding: 4,
formatter: function(value) {

Check warning on line 55 in front/src/components/boxs/chart/ApexChartAreaOptions.js

View workflow job for this annotation

GitHub Actions / Front test

Expected method shorthand
if (Math.abs(value) < 1) {
return value; // For very low values, like crypto prices, use the normal value
} else {

Check warning on line 58 in front/src/components/boxs/chart/ApexChartAreaOptions.js

View workflow job for this annotation

GitHub Actions / Front test

Unnecessary 'else' after 'return'
return value.toFixed(2); // 2 decimal places for other values
}
}
}
},
colors,
Expand Down
9 changes: 8 additions & 1 deletion front/src/components/boxs/chart/ApexChartBarOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@
},
yaxis: {
labels: {
padding: 4
padding: 4,
formatter: function(value) {

Check warning on line 63 in front/src/components/boxs/chart/ApexChartBarOptions.js

View workflow job for this annotation

GitHub Actions / Front test

Expected method shorthand
if (Math.abs(value) < 1) {
return value; // For very low values, like crypto prices, use the normal value
} else {

Check warning on line 66 in front/src/components/boxs/chart/ApexChartBarOptions.js

View workflow job for this annotation

GitHub Actions / Front test

Unnecessary 'else' after 'return'
return value.toFixed(2); // 2 decimal places for other values
}
}
}
},
colors,
Expand Down
9 changes: 8 additions & 1 deletion front/src/components/boxs/chart/ApexChartLineOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ const getApexChartLineOptions = ({ height, displayAxes, series, colors, locales,
},
yaxis: {
labels: {
padding: 4
padding: 4,
formatter: function(value) {
if (Math.abs(value) < 1) {
return value; // For very low values, like crypto prices, use the normal value
} else {
return value.toFixed(2); // 2 decimal places for other values
}
}
}
},
colors,
Expand Down
9 changes: 8 additions & 1 deletion front/src/components/boxs/chart/ApexChartStepLineOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,14 @@ const getApexChartStepLineOptions = ({ height, displayAxes, series, colors, loca
},
yaxis: {
labels: {
padding: 4
padding: 4,
formatter: function(value) {
if (Math.abs(value) < 1) {
return value; // For very low values, like crypto prices, use the normal value
} else {
return value.toFixed(2); // 2 decimal places for other values
}
}
}
},
colors,
Expand Down
22 changes: 19 additions & 3 deletions front/src/config/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"fahrenheit": "F",
"metersPerSec": "m/s",
"milesPerHour": "m/h",
"selectPlaceholder": "Auswählen …"
"selectPlaceholder": "Auswählen …",
"yes": "Ja",
"no": "Nein"
},
"color": {
"aqua": "Aqua",
Expand Down Expand Up @@ -231,6 +233,7 @@
"houseLabel": "Zuhause",
"tabletModeDisabled": "Tablet-Modus deaktiviert"
},
"duckDbMigrationInProgress": "Ihre Instanz Gladys ist dabei, ihre Datenbank auf DuckDB umzustellen, ein neues, leistungsfähigeres Datenbanksystem für Zeitseriendaten. Diese Aufgabe kann einige Zeit in Anspruch nehmen, und während dieser Zeit werden nicht alle Ihre Grafiken verfügbar sein. Fortschritt der Migration = {{progress}}%",
"editDashboardSaveButton": "Sichern",
"emptyDashboardSentenceTop": "Dein Dashboard wurde noch nicht konfiguriert.",
"emptyDashboardSentenceBottom": "Klicke auf \"Bearbeiten\", um dein Dashboard zu gestalten.",
Expand Down Expand Up @@ -2362,7 +2365,9 @@
"gladys-gateway-backup": "Gladys-Plus-Backup",
"device-state-purge-single-feature": "Zustände einzelner Gerätemerkmale aufräumen",
"vacuum": "Datenbank reinigen",
"service-zigbee2mqtt-backup": "Zigbee2MQTT-Backup"
"service-zigbee2mqtt-backup": "Zigbee2MQTT-Backup",
"migrate-sqlite-to-duckdb": "DuckDB migration",
"device-state-purge-all-sqlite-states": "Bereinigung aller SQLite-Berichte"
},
"jobErrors": {
"purged-when-restarted": "Gladys Assistant wurde neu gestartet, während diese Aufgabe noch lief. Daher wurde sie gelöscht. Das bedeutet nicht, dass die Aufgabe fehlgeschlagen ist – es handelt sich um normales Verhalten."
Expand Down Expand Up @@ -2415,7 +2420,18 @@
"dead": "Beendet"
},
"batteryLevel": "Batteriestandswarnung",
"batteryLevelDescription": "Jeden Samstag um 9:00 Uhr wird eine Nachricht an alle Administratoren gesendet, wenn der Batteriestand eines Geräts unter den gewählten Schwellenwert fällt."
"batteryLevelDescription": "Jeden Samstag um 9:00 Uhr wird eine Nachricht an alle Administratoren gesendet, wenn der Batteriestand eines Geräts unter den gewählten Schwellenwert fällt.",
"duckDbMigrationTitle": "Migration zu DuckDB",
"duckDbMigrationDescription": "Wir migrieren zu einem neuen Datenbanksystem für Sensordaten. Gladys wird Ihre Daten automatisch migrieren, aber Ihre Daten in Ihrer SQLite-Datenbank nicht löschen, um Datenverlust zu vermeiden.",
"duckDbMigrationProgressTitle": "Migrationsfortschritt",
"duckDbMigrationMigrationDone": "Migration abgeschlossen:",
"duckDbNumberOfStatesinSQlite": "Anzahl der Zustände in SQLite",
"duckDbNumberOfStatesinDuckDb": "Anzahl der Zustände in DuckDB",
"restartMigrationTitle": "Migration neu starten",
"confirm": "Bestätigen",
"cancel": "Abbrechen",
"purgeSQliteTitle": "SQLite-Zustände löschen",
"purgeSQliteDescription": "Sobald alle Zustände aus SQLite gelöscht wurden, müssen Sie auf der rechten Registerkarte eine \"Datenbankbereinigung\" durchführen, um Speicherplatz freizugeben. Dieser Schritt kann einige Zeit in Anspruch nehmen."
},
"newArea": {
"createNewZoneButton": "Neue Zone erstellen",
Expand Down
22 changes: 19 additions & 3 deletions front/src/config/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"fahrenheit": "F",
"metersPerSec": "m/s",
"milesPerHour": "m/h",
"selectPlaceholder": "Select..."
"selectPlaceholder": "Select...",
"yes": "Yes",
"no": "No"
},
"color": {
"aqua": "Aqua",
Expand Down Expand Up @@ -231,6 +233,7 @@
"houseLabel": "House",
"tabletModeDisabled": "Tablet Mode Disabled"
},
"duckDbMigrationInProgress": "Votre instance Gladys est entrain de migrer sa base de donnée à DuckDB, un nouveau système de base de donnée plus performant pour les données time-series. Cette tâche peut prendre un certain temps, et pendant ce temps vos graphiques ne seront pas tous disponibles. Progression de la migration = {{progress}}%",
"editDashboardSaveButton": "Save",
"emptyDashboardSentenceTop": "Looks like your dashboard is not configured yet.",
"emptyDashboardSentenceBottom": "Click on the \"Edit\" button to design your dashboard.",
Expand Down Expand Up @@ -2362,7 +2365,9 @@
"gladys-gateway-backup": "Gladys Plus backup",
"device-state-purge-single-feature": "Single device feature states clean",
"vacuum": "Database cleaning",
"service-zigbee2mqtt-backup": "Zigbee2MQTT backup"
"service-zigbee2mqtt-backup": "Zigbee2MQTT backup",
"migrate-sqlite-to-duckdb": "DuckDB migration",
"device-state-purge-all-sqlite-states": "Purge all SQLite states"
},
"jobErrors": {
"purged-when-restarted": "Gladys Assistant restarted while this job was still running, so it was purged. It doesn't mean the job has failed, it's a normal behavior."
Expand Down Expand Up @@ -2415,7 +2420,18 @@
"dead": "Dead"
},
"batteryLevel": "Battery level alert",
"batteryLevelDescription": "Every Saturday at 9:00 am, a message will be sent to all administrators if a device's battery level falls below the chosen threshold."
"batteryLevelDescription": "Every Saturday at 9:00 am, a message will be sent to all administrators if a device's battery level falls below the chosen threshold.",
"duckDbMigrationTitle": "Migration to DuckDB",
"duckDbMigrationDescription": "We are migrating to a new database system for sensor data. Gladys will automatically migrate your data, but will not delete your data from your SQLite database to prevent data loss.",
"duckDbMigrationProgressTitle": "Migration Progress",
"duckDbMigrationMigrationDone": "Migration completed:",
"duckDbNumberOfStatesinSQlite": "Number of states in SQLite",
"duckDbNumberOfStatesinDuckDb": "Number of states in DuckDB",
"restartMigrationTitle": "Restart Migration",
"confirm": "Confirm",
"cancel": "Cancel",
"purgeSQliteTitle": "Purge SQLite states",
"purgeSQliteDescription": "Once all states are deleted from SQLite, you will need to perform a \"database cleanup\" on the tab to the right to free up disk space. This step may take some time."
},
"newArea": {
"createNewZoneButton": "Create new zone",
Expand Down
22 changes: 19 additions & 3 deletions front/src/config/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"fahrenheit": "F",
"metersPerSec": "m/s",
"milesPerHour": "m/h",
"selectPlaceholder": "Sélectionnez..."
"selectPlaceholder": "Sélectionnez...",
"yes": "Oui",
"no": "Non"
},
"color": {
"aqua": "Aqua",
Expand Down Expand Up @@ -229,6 +231,7 @@
"houseLabel": "Maison",
"tabletModeDisabled": "Mode tablette désactivé"
},
"duckDbMigrationInProgress": "Votre instance Gladys est en train de migrer sa base de données à DuckDb, un nouveau système de base de données plus performant pour les données time-series. Cette tâche peut prendre un certain temps, et pendant ce temps vos graphiques ne seront pas tous disponibles. Progression de la migration = {{progress}}%",
"enableFullScreen": "Plein écran",
"disableFullScreen": "Quitter plein écran",
"editDashboardTitle": "Éditer le tableau de bord",
Expand Down Expand Up @@ -2362,7 +2365,9 @@
"device-state-purge-single-feature": "Nettoyage des états d'un appareil",
"device-state-purge": "Nettoyage des vieux états d'appareils",
"vacuum": "Nettoyage de la base de données",
"service-zigbee2mqtt-backup": "Sauvegarde Zigbee2MQTT"
"service-zigbee2mqtt-backup": "Sauvegarde Zigbee2MQTT",
"migrate-sqlite-to-duckdb": "Migration vers DuckDb",
"device-state-purge-all-sqlite-states": "Purge de tous les états SQLite"
},
"jobErrors": {
"purged-when-restarted": "Gladys Assistant a redémarré alors que cette tâche était en cours. Cela ne veut pas dire que cette tâche a échouée, c'est un comportement normal."
Expand Down Expand Up @@ -2415,7 +2420,18 @@
"dead": "Mort"
},
"batteryLevel": "Alerte sur le niveau de batterie",
"batteryLevelDescription": "Tous les samedis à 9h00, un message sera envoyé à tous les administrateurs si le niveau de batterie d'un appareil passe en dessous du seuil choisi."
"batteryLevelDescription": "Tous les samedis à 9h00, un message sera envoyé à tous les administrateurs si le niveau de batterie d'un appareil passe en dessous du seuil choisi.",
"duckDbMigrationTitle": "Migration vers DuckDB",
"duckDbMigrationDescription": "Nous migrons vers un nouveau système de base de donnée pour les données de capteurs. Gladys va effectuer une migration de vos données automatiquement, mais ne supprimera pas vos données de votre base SQLite afin d'éviter les pertes de données.",
"duckDbMigrationProgressTitle": "Avancement de la migration",
"duckDbMigrationMigrationDone": "Migration effectuée :",
"duckDbNumberOfStatesinSQlite": "Nombre d'états dans SQLite",
"duckDbNumberOfStatesinDuckDb": "Nombre d'états dans DuckDB",
"restartMigrationTitle": "Relancer la migration",
"confirm": "Confirmer",
"cancel": "Annuler",
"purgeSQliteTitle": "Purger les états SQLite",
"purgeSQliteDescription": "Une fois que tous les états seront supprimés de SQLite, vous devrez faire un \"nettoyage de la base de données\" sur l'onglet à droite afin de relâcher l'espace disque. Cette étape peut prendre un certain temps."
},
"newArea": {
"createNewZoneButton": "Créer une zone",
Expand Down
6 changes: 6 additions & 0 deletions front/src/routes/dashboard/DashboardPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cx from 'classnames';
import BoxColumns from './BoxColumns';
import EmptyState from './EmptyState';
import SetTabletMode from './SetTabletMode';
import { JOB_STATUS } from '../../../../server/utils/constants';

import style from './style.css';

Expand Down Expand Up @@ -85,6 +86,11 @@ const DashboardPage = ({ children, ...props }) => (
toggleDefineTabletMode={props.toggleDefineTabletMode}
defineTabletModeOpened={props.defineTabletModeOpened}
/>
{props.duckDbMigrationJob && props.duckDbMigrationJob.status === JOB_STATUS.IN_PROGRESS && (
<div class="alert alert-info">
<Text id="dashboard.duckDbMigrationInProgress" fields={props.duckDbMigrationJob} />
</div>
)}
{props.dashboardNotConfigured && <EmptyState dashboardListEmpty={props.dashboardListEmpty} />}
{!props.dashboardNotConfigured && <BoxColumns homeDashboard={props.currentDashboard} />}
</div>
Expand Down
Loading
Loading