Live Coding: Découverte de DuckDB le jeudi 20 juin à 10h!

C’est dur de prévoir le temps de transfert, ça dépend de plein de facteurs, la vitesse du disque principalement, c’est vraiment unique à chaque hardware.

La partie « transfert » n’est pas bloquante, Gladys peut-être utilisé en même temps.

En revanche, pendant la durée du transfert, les graphiques ne seront pas forcément disponibles, je dois encore décider si je laisse le double code à vie dans Gladys, où si on élimine le code et du coup le temps de la migration, les graphiques seront vide, ce qui est peut-être un tradeoff acceptable.

Par contre, ce qui est bloquant, c’est la partie « VACUUM » de la DB SQLite pour faire la réduction de la taille du disque « finale », et ça à voir si on le fait en forcé, ou si on demande à l’utilisateur de le faire. C’est sûrement plus intelligent de demander à l’utilisateur de le faire pour ne pas bloquer son instance.

Pour info, sur mon disque le VACUUM de ta DB de 13GB a duré 30 secondes, mais je suis sur un Macbook Pro du futur (10 coeurs CPU / SSD NVMe à 4.5GB/s de débit ), sur Pi ça va prendre un sacré moment je pense

Je te conseille de le faire quand même, tu vas recevoir des alertes tous les jours maintenant que la 4.44 est sortie.

Et je suis vraiment pas prêt de sortir la version avec DuckDB, j’avais parlé de mois :slight_smile:

1 « J'aime »

Journée de développement très productive aujourd’hui !

Pour vous tenir au courant, ce qui est codé :

  • Insertion des états dans DuckDB au lieu de SQLite :white_check_mark:
  • Requêtes API graphique via DuckDB :white_check_mark:
  • Suppression des tâches d’agrégations obsolètes :white_check_mark:
  • Tâche de migration de base de donnée :white_check_mark:

(Je code les tests en même temps, donc tout ce qui est fait est testé)

En cours de développement :

  • Sauvegarde et restauration Gladys Plus :construction:

La sauvegarde ne se fera pas en sauvegardant juste le fichier .duckdb, duckDB permet une API qui exporte un fichier compressé .parquet (Parquet, qu’est ce que c’est ?) un format dédié aux données time-serie. Ce format de fichier est néanmoins un poil plus lourd en stockage qu’un fichier DuckDB, après je suis les recommandations DuckDB et l’API officiel de export/import. Je ne pense pas qu’il soit smart de copier un fichier .duckdb à chaud pour faire une sauvegarde.

  • Feedback clean dans l’interface lors de la migration :construction:

L’interface doit-être très clair et expliquer ce qui se passe à l’utilisateur.

A faire :

  • Voir à quel moment on supprime les données dans SQLite. Pour l’instant j’ai choisi de ne pas les supprimer automatiquement pour éviter les pertes de données, et de laisser le choix à l’utilisateur de supprimer à posteriori lui même ces données via un bouton dans l’interface (pas encore codé) :x:
  • Test en réel et optimisation de la migration sur des instances avec beaucoup de données et faible puissance CPU/disque :x:
  • Test d’interruption et de reprise de migration :x:
  • Test multi-jours/semaines en réel de l’utilisation de Gladys avec DuckDB. Objectif : vérifier la stabilité/zéro crash accepté :x:
  • Sûrement des choses que j’ai oublié :smile:

Je vous tiens au courant !

6 « J'aime »

Waw! Pour un projet sur plusieurs mois… On sent la motivation :wink:.
Je vais déjà te rectifier : « en train de (…) vers DuckDB » sera plus correct et « un certain temps pendant lequel vos » plus joli. Ainsi, c’est fait ! :innocent:
Pour rappel, j’ai un RPi2 et un zero2W (équivalent RPi3) dispos pour des tests. Et je suis enseignant donc libre en été…

2 « J'aime »

J’ai encore bien avancé aujourd’hui, l’utilisateur pourra suivre si la migration a bien eu lui dans l’onglet système :

Il pourra lui même purger les états SQLite (ce ne sera pas automatique dans un premier temps, pour laisser le contrôle à l’utilisateur).

Dans l’onglet « Tâches », il peut voir en direct l’avancement de la tâche de migration / les erreurs si il y en a :

4 « J'aime »

C’est propre comme interface, je trouve, cool. J’imagine que le bouton « purger les états SQLite » ne sera pas actionnable tant que la migration ne sera pas faite…

Et par contre, si je trouve bien qu’il faille une action manuelle pour supprimer les données de la base SQLite, je ne vois pas l’intérêt, d’un point de vue utilisateur, de devoir faire deux actions manuelles : purger, puis nettoyer. Il y a une raison à cela ?

Pas bête, je vais changer ça :slight_smile: c’était pas le cas actuellement !

Purger c’est une action qui se fait en background et qui est non bloquante. Tu peux faire tourner la purge en pleine journée sans soucis, ça supprime par batch petit à petit. Ça peut prendre du temps par contre, mais c’est non bloquant.

Le nettoyage est une commande SQLite (« VACUUM ») qui est bloquante, Gladys est entièrement bloquée pendant son action. Sur un disque SSD NVMe très performant sur un mini PC, le blocage sera limité en temps.

Sur un SSD en USB sur un Pi, ou pire sur une carte SD, le blocage peut prendre plusieurs heures (c’est précisé du côté du bouton nettoyage)

Donc j’ai préféré séparer les deux actions pour que l’utilisateur ait le choix de timer quand il veut faire chaque action.

Si on met les deux à la chaîne, et que tu lance la purge, que Gladys tourne, puis 2h plus tard ça passe au nettoyage et que Gladys se bloque, l’utilisateur risque de ne pas comprendre et pensera que c’est un bug !

3 « J'aime »

Très clair. Et le choix que tu fais est donc le bon.

J’en profite pour te remercie de la pédagogie dont tu fais preuve régulièrement pour répondre aux questions des uns et des autres sur ce forum :+1:

5 « J'aime »

J’ai lancé un build Docker manuel en début d’après midi pour faire des tests sur Raspberry Pi…

Et ça tourne toujours !! ^^ (40 min d’habitude)

Visiblement, le build armv6 est très lent depuis que duckdb est dans les dépendances, ça doit faire une compilation totale de DuckDB à mon avis

Edit: Confirmé dans les issue Github de DuckDB, ils fournissent des build pour arm64, mais pas pour armv7 ni armv6

Je n’y connais rien mais, ça ne peut pas être mis dans un système du genre ‹ en cache ›?
Si pas, ça va être pénible pour toi !

C’est déjà le cas :slight_smile: Dans tous les cas, il faut bien un premier build pour initialiser le cache / renouveler le cache quand les dépendances changent

ça aura mis plus de 4h en tout cas :

Après, la question du support d’armv6/v7 se pose, on a d’autres sujets qui ne fonctionnent plus sur armv6 (Node 20) notamment, et on va sûrement vite être poussé à abandonner cette plateforme… (fini les Pi Zero notamment, mais bon est-ce que Gladys a vraiment vocation a tourner sur ces machines, sachant que déjà sur un Pi 3/4 ça tourne pas terrible ^^)

1 « J'aime »

Salut à tous !

Aujourd’hui, test de performance de l’image Docker avec DuckDB sur un Pi (pour tester sur un environnement volontairement lent)

L’image Docker que j’utilise :

gladysassistant/gladys:duckdb
3 « J'aime »

Ça a un intérêt pour toi que je lance l’image sur un pizero 2 ?
Ou sur mon pi 4 de prod (4Gb de RAM -après backup de la db évidemment) ?

Pas pour l’instant :slight_smile: L’image ne marche même pas pour l’instant :joy:

1 « J'aime »

Bon, je viens enfin de réussir à faire fonctionner l’image !

Par contre j’ai du passer d’une image Docker node-alpine à node-slim, DuckDB ne s’installe pas bien sur Alpine…

Pour l’instant, la taille de l’image Docker augmente pas mal, mais je pense qu’il y a des optimisations à faire.

En attendant, la migration DuckDB sur Pi 3 s’est bien passé :

2024-08-02T16:24:51+0200 <info> device.migrateFromSQLiteToDuckDb.js:39 (DeviceManager.migrateFromSQLiteToDuckDb) DuckDB: Migrating data from SQLite
2024-08-02T16:24:51+0200 <info> index.js:64 (Server.<anonymous>) Server listening on port 80
2024-08-02T16:24:51+0200 <info> device.migrateFromSQLiteToDuckDb.js:47 (DeviceManager.migrateFromSQLiteToDuckDb) DuckDB: Found 0 already migrated device features in DuckDB.
2024-08-02T16:24:51+0200 <info> device.migrateFromSQLiteToDuckDb.js:51 (DeviceManager.migrateFromSQLiteToDuckDb) DuckDB: Migrating 3 device features
2024-08-02T16:24:51+0200 <info> device.migrateFromSQLiteToDuckDb.js:8 (migrateStateRecursive) DuckDB : Migrating device feature = 91f39b3d-d747-4fd0-9880-8bc1e8f9067e, offset = 0
2024-08-02T16:24:51+0200 <info> device.migrateFromSQLiteToDuckDb.js:11 (migrateStateRecursive) DuckDB : Device feature = 91f39b3d-d747-4fd0-9880-8bc1e8f9067e has 0 states to migrate.
2024-08-02T16:24:51+0200 <info> device.migrateFromSQLiteToDuckDb.js:8 (migrateStateRecursive) DuckDB : Migrating device feature = 813c1830-b494-4f01-b339-1f287f621548, offset = 0
2024-08-02T16:24:54+0200 <info> device.migrateFromSQLiteToDuckDb.js:11 (migrateStateRecursive) DuckDB : Device feature = 813c1830-b494-4f01-b339-1f287f621548 has 34723 states to migrate.
2024-08-02T16:24:55+0200 <info> index.js:130 () DuckDB : Inserting chunk 0 for deviceFeature = 813c1830-b494-4f01-b339-1f287f621548.
2024-08-02T16:25:00+0200 <info> scene.checkCalendarTriggers.js:25 (SceneManager.checkCalendarTriggers) Checking calendar triggers at Fri, 02 Aug 2024 14:25:00 GMT
2024-08-02T16:25:02+0200 <info> index.js:130 () DuckDB : Inserting chunk 1 for deviceFeature = 813c1830-b494-4f01-b339-1f287f621548.
2024-08-02T16:25:09+0200 <info> index.js:130 () DuckDB : Inserting chunk 2 for deviceFeature = 813c1830-b494-4f01-b339-1f287f621548.
2024-08-02T16:25:16+0200 <info> index.js:130 () DuckDB : Inserting chunk 3 for deviceFeature = 813c1830-b494-4f01-b339-1f287f621548.
2024-08-02T16:25:19+0200 <info> device.migrateFromSQLiteToDuckDb.js:8 (migrateStateRecursive) DuckDB : Migrating device feature = 813c1830-b494-4f01-b339-1f287f621548, offset = 40000
2024-08-02T16:25:19+0200 <info> device.migrateFromSQLiteToDuckDb.js:11 (migrateStateRecursive) DuckDB : Device feature = 813c1830-b494-4f01-b339-1f287f621548 has 0 states to migrate.
2024-08-02T16:25:20+0200 <info> device.migrateFromSQLiteToDuckDb.js:8 (migrateStateRecursive) DuckDB : Migrating device feature = 24e039f2-d497-468a-87ee-517a1e67923d, offset = 0
2024-08-02T16:25:20+0200 <info> device.migrateFromSQLiteToDuckDb.js:11 (migrateStateRecursive) DuckDB : Device feature = 24e039f2-d497-468a-87ee-517a1e67923d has 10272 states to migrate.
2024-08-02T16:25:21+0200 <info> index.js:130 () DuckDB : Inserting chunk 0 for deviceFeature = 24e039f2-d497-468a-87ee-517a1e67923d.
2024-08-02T16:25:27+0200 <info> index.js:130 () DuckDB : Inserting chunk 1 for deviceFeature = 24e039f2-d497-468a-87ee-517a1e67923d.
2024-08-02T16:25:27+0200 <info> device.migrateFromSQLiteToDuckDb.js:8 (migrateStateRecursive) DuckDB : Migrating device feature = 24e039f2-d497-468a-87ee-517a1e67923d, offset = 40000
2024-08-02T16:25:27+0200 <info> device.migrateFromSQLiteToDuckDb.js:11 (migrateStateRecursive) DuckDB : Device feature = 24e039f2-d497-468a-87ee-517a1e67923d has 0 states to migrate.
2024-08-02T16:25:27+0200 <info> device.migrateFromSQLiteToDuckDb.js:76 (DeviceManager.migrateFromSQLiteToDuckDb) DuckDB: Finished migrating DuckDB.

Ma tâche « Supprimer les états dans SQlite » est peut-être trop aggressive, sur un Pi 3 sur carte SD ça rend Gladys difficilement utilisable pendant la migration, après ça reste un setup pas recommandé

2 « J'aime »

@GBoulvin (et les autres!) Si tu veux tester cette fois-ci c’est bon, en revanche dispo uniquement sur architecture amd64 ou arm64 (pas de Pi Zero donc pour l’instant)

Ce que je te recommande si tu veux tester, c’est de faire ça totalement à côté de ta prod, le mieux ce serait sur une machine séparée de ta prod :slight_smile:

:warning::warning: Sinon, si tu n’as que ton Pi 4 de prod, il faut absolument faire ça sur un autre dossier que ta DB de prod, cette mise à jour est majeure et le rétropédalage sur l’image gladys:v4 actuellement en prod n’est pas possible :warning::warning:

:warning: Je précise qu’ayant changé d’OS pour l’image Docker, certaines intégrations « natives » ne fonctionnent peut-être plus (ex: Bluetooth, ou autre), il y a de la QA à faire que je n’ai pas encore fait pour l’instant ^^

L’image Docker :

gladysassistant/gladys:duckdb

N’hésite pas si tu as des retours :wink:

L’image fonctionne bien pour le moment. La migration de la base à pris environ 15 minutes.
Ma base de production sqlite fait 7Go, la duckdb 27Mo.
RPI4 8Go avec SSD
Premier retour, les valeurs ne sont pas tronquées / arrondies

Merci du retour @cicoub13 ! Tu l’as laissé tourner ou juste testé une fois ?

Pour les arrondis je suis au courant, j’avais fais une PR séparée car le souci est déjà présent en prod actuellement, mais je pense que je vais merger cette PR dans la PR DuckDB et refaire un build!

Ça tourne depuis vendredi.
Zigbee2Mqtt / MQTT / Enedis / OpenWeather / Caméra et Télégram OK

1 « J'aime »

Je viens de merge la PR pour retirer les zéros en trop des graphiques et de relancer un build

Build time environ 4h15 :sweat_smile:

Edit: dingue, avec le cache docker ça n’a pris que 1 minute :slight_smile:

@cicoub13 tu peux mettre à jour ton image en local pour avoir les graphiques sans 0 !

J’ai essayé de slimmer la taille de l’image Docker, j’ai relancé un build !