Journal trsync : un outil de synchronisation bidirectionnelle pour travailler hors-ligne avec tracim

21
1
oct.
2021

Je viens de stabiliser une toute première version du programme trsync. Il permet de synchroniser un dossier local avec un espace de partage Tracim. L'objectif : Travailler localement sur ses fichiers hébergés sur un un serveur Tracim et ne pas se préoccuper de la synchronisation.

trsync illustration

Vidéo de démonstration : https://tracim.bux.fr/api/public/guest-download/cfe77068-7a30-4afb-8a54-ef4360039d82/TracimRemoteSync.webm

Pourquoi avoir commencé ce logiciel ?

J'aime et je promeus le logiciel libre. Je suis développeur. J'utilise à titre personnel Tracim pour gérer des documents personnels et professionnels de type documentation et Seafile pour un peu tout le reste (musique, photos, etc). J'avais envie depuis quelque temps de tout passer sur Tracim et le seul point bloquant pour mon usage était la synchro locale et « hors-ligne » de mes fichiers. Je me suis donc lancé dans ce projet. En plus, c'était l'occasion de faire du Rust \o/

Compiler et installer trsync

Pour compiler trsync, les étapes sont les suivantes :

Le tester

Le projet est tout neuf, mais peu d'ores et déjà être testé. Vous pouvez par exemple l'essayer avec mon.tracim.fr (ou sur votre propre Tracim si vous en avez un).

Aujourd'hui trsync n'est dispo qu'en version de développement, donc il faudra nécessairement compiler vous-même le programme (cf section précédente)

Ensuite, pour tester, c'est relativement simple :

  • Créer un compte ou se connecter sur https://mon.tracim.fr
  • Relever l'identifiant de l'espace partagé que vous voulez synchroniser

    mon tracim example

  • Lancer le processus de synchronisation depuis le dossier des sources (dans un terminal) : cargo run /mon/dossier/Tracim/Test mon.tracim.fr 14 MonUserNameSurMonTracimFr

À noter que le processus est conçu comme un démon et si vous le laissez tourner il fera la synchronisation en temps réel en fonction de vos actions locales ou des actions réalisées par d'autres personnes sur le serveur

Comment ça marche ?

Tout le fonctionnement du programme repose sur les éléments suivants :

  • Tracim propose une communication bidirectionnelle :
    • une API REST permettant de faire des opérations sur le serveur (transmission d'informations du client vers le serveur)
    • un socket SSE permettant d'être informé des opérations qui sont réalisés sur le serveur (transmission d'informations du serveur vers le client)
  • trsync écoute le système de fichier local en s'appuyant sur inotify (ou équivalent selon le système d'exploitation)
  • trsync gère un index local représentant l'état local et l'état distant.

Dans les grandes lignes, l'algorithme de trsync est le suivant :

  • Au démarrage :
    • Compare l'état des fichiers du dossier avec l'index
    • Compare l'état des fichiers sur Tracim avec l'index
  • Puis :
    • Surveille les changements locaux (à l'aide de inotify par exemple)
    • Surveille les changements sur Tracim (à l'aide des TLM introduits dans la version 3)
  • Chaque changement donne suite à une résolution qui consiste à modifier les fichiers locaux ou sur Tracim tout en maintenant l'index local.

Comme évoqué précédemment, tout le fonctionnement repose sur les APIs standards de Tracim : API REST intégrées dans Tracim 2 et SSE intégrés dans Tracim 3 (tiens, d'ailleurs, on attend toujours la dépêche promise en janvier dernier au sujet de la nouvelle version ;)

C'est l'occasion de contribuer à un projet opensource et de vous mettre au Rust ;)

Pourquoi avoir choisi Rust ?

Parce qu'à mon avis et avec mes quelques années d'expériences sur ce langage, c'est le meilleur choix pour un programme que je souhaite aussi maintenable et stable que possible. Il est notamment très adapté dans le contexte de trsync pour les raisons suivantes :

  • doit pouvoir être déployé sur des machines quelconques (Linux, Windows, MacOS)
  • doit pouvoir évoluer vers une interface graphique - des bindings QT (entre autres) existent pour Rust
  • travail nativement en exécution parallèle (envoi d'instructions sur le serveur Tracim en parallèle de l'écoute du socket SSE) -> Rust est idéal pour ça.

Let's go

Je suis preneur de toutes les idées, remarques et remontées de bugs ! Et bien sûr de toute contribution !

Pour celles et ceux qui souhaitent le faire directement sur la forge : https://github.com/buxx/trsync

  • # Super initiative ! :)

    Posté par  (site Web personnel) . Évalué à 7. Dernière modification le 01/10/21 à 10:52.

    Le projet m'intéresse vivement (et pour cause : je suis le créateur de Tracim;)

    Pourquoi avoir limité à un identifiant d'espace ? (s'il y a une autre raison que : "c'est la première étape)

    À chaud, j'ai l'impression qu'une première requête d'API permettrait de récupérer la liste des identifiants d'espace et en conséquence de synchroniser l'ensemble.

    Autre question : j'avais prévu/envisagé de faire un client (en python) s'intégrant à l'environnement graphique du client et en particulier l'espace de notifications. Est-ce que Rust permet de faire des lib dynamiques que l'on pourrait exploiter via un code en python ou autre ? Est-ce envisageable sur ce projet ?

    Quelle est la manière la plus efficace aujourd'hui pour contribuer ? (sachant que je ne connais pas le langage Rust, j'imagine plutôt de contribuer autrement que sous forme de code)

    C'est une super initiative je trouve !!!

    • [^] # Re: Super initiative ! :)

      Posté par  (site Web personnel) . Évalué à 2.

      Pourquoi avoir limité à un identifiant d'espace ? (s'il y a une autre raison que : "c'est la première étape)

      Honnêtement je suis allé volontairement au plus simple pour commencer. En m'imaginant qu'un programme "au-dessus" s'occuperais de gérer un processus par espace partagé. Mais à ce stade, rien n'est figé.

      Est-ce que Rust permet de faire des lib dynamiques que l'on pourrait exploiter via un code en python ou autre ?

      Oui, je n'ai pas essayé mais c'est très en vogue !

      Est-ce envisageable sur ce projet ?

      Pourquoi pas :)

      Quelle est la manière la plus efficace aujourd'hui pour contribuer ? (sachant que je ne connais pas le langage Rust, j'imagine plutôt de contribuer autrement que sous forme de code)

      À mon avis : tester, remonter des bugs, bidouiller la CI de Github, réfléchir aux évolutions fonctionnelles et intégrations possibles.

      C'est une super initiative je trouve !!!

      Merci !

      Blog: http://blog.bux.fr, github: http://github.com/buxx

      • [^] # Re: Super initiative ! :)

        Posté par  . Évalué à 2. Dernière modification le 01/10/21 à 11:36.

        Ça semble sympa ;)

        Petites questions pratique :

        • Y a-t-il une indication à l’utilisateur lorsqu’il y a de la synchronisation en court ? (quantité de données à télécharger vs à téléverser, temps restant, débit actuel).
        • Y a-t-il un moyen de dire “je ne souhaite pas synchroniser” par exemple si l’on est connecté à une connexion internet lente ?
        • Que se passe-t-il si la connexion internet est coupé lors de la synchronisation ? (surtout pour le cas où je ne sais pas qu’il y a des échanges de données en cours actuellement).
        • Les mises à jour dans Tracim génère-t-elle des notifications dans l’application (au même titre que les autres contenus).
        • est-il prévu une option pour choisir par exemple de ne synchroniser que dans un seul sens (genre je voudrais avoir une sorte de Backup automatique des données, mais je veux pouvoir supprimer des données localement sans que la suppression se répercute dans Tracim).

        En tout cas good job :)

        • [^] # Re: Super initiative ! :)

          Posté par  (site Web personnel) . Évalué à 3.

          Y a-t-il une indication à l’utilisateur lorsqu’il y a de la synchronisation en court ? (quantité de données à télécharger vs à téléverser, temps restant, débit actuel).

          Point du tout, trsync est vraiment ultra basique pour le moment. Les logs sont d'ailleurs assez affreux à ce stade :)

          Y a-t-il un moyen de dire “je ne souhaite pas synchroniser” par exemple si l’on est connecté à une connexion internet lente ?

          Non

          Que se passe-t-il si la connexion internet est coupé lors de la synchronisation ? (surtout pour le cas où je ne sais pas qu’il y a des échanges de données en cours actuellement).

          Ca plante !

          Les mises à jour dans Tracim génère-t-elle des notifications dans l’application (au même titre que les autres contenus).

          Oui (si tu parles du fait de modifier un fichier sur ton disque dur, qui produit une mise à jour de contenu sur Tracim).

          est-il prévu une option pour choisir par exemple de ne synchroniser que dans un seul sens (genre je voudrais avoir une sorte de Backup automatique des données, mais je veux pouvoir supprimer des données localement sans que la suppression se répercute dans Tracim).

          non

          --> Cet ensemble de questions fait une bonne liste de tickets de fonctionnalités :)

          Blog: http://blog.bux.fr, github: http://github.com/buxx

  • # Liste de fichiers ignorés, prise en charge des notes

    Posté par  . Évalué à 4. Dernière modification le 01/10/21 à 11:57.

    Je suis preneur de toutes les idées, remarques et remontées de bugs !

    Eh bien c'est parti ! :-)

    • Avoir une liste de fichiers / dossiers ignorés dans le style des fichiers .gitignore pour Git. Une liste soit locale, soit synchronisée sur Tracim.
    • Pouvoir éditer les notes. Webdav permet de récupérer les notes qui ont une extension .document.html mais ne permet pas de les modifier. L'extension pourrait être reprise, mais le comportement de la synchronisation pour ces fichiers devra appeler les API relatives aux notes (avec un éditeur de code ou un outil WYSIWYG indépendant de trsync qui ne s'occuperait que de la synchronisation elle-même).
    • avoir une petite icône / l'état de la synchronisation dans la zone de notifications de l'environnement de bureau (?)

    Félicitations pour ce projet.

    • [^] # Re: Liste de fichiers ignorés, prise en charge des notes

      Posté par  (site Web personnel) . Évalué à 1.

      Avoir une liste de fichiers / dossiers ignorés dans le style des fichiers .gitignore pour Git. Une liste soit locale, soit synchronisée sur Tracim.

      Pouvoir éditer les notes. Webdav permet de récupérer les notes qui ont une extension .document.html mais ne permet pas de les modifier. L'extension pourrait être reprise, mais le comportement de la synchronisation pour ces fichiers devra appeler les API relatives aux notes (avec un éditeur de code ou un outil WYSIWYG indépendant de trsync qui ne s'occuperait que de la synchronisation elle-même).

      Il y a même déjà un ticket pour ça https://github.com/buxx/trsync/issues/9 et https://github.com/buxx/trsync/issues/8

      avoir une petite icône / l'état de la synchronisation dans la zone de notifications de l'environnement de bureau (?)

      Je note !

      Félicitations pour ce projet.

      Merci !

      Blog: http://blog.bux.fr, github: http://github.com/buxx

  • # Retour d'expérience

    Posté par  (site Web personnel) . Évalué à 10.

    Salut,

    j'ai bossé il y a quelques années sur le client desktop de synchro de fichiers pour Cozy Cloud, et même si je n'ai plus les mains dedans, je continue de suivre les développements, les retours des utilisateurs, et de réfléchir à des idées pour l'améliorer. C'est probablement l'un des projets les plus difficiles sur lequel j'ai eu à travailler, mais aussi l'un des plus intéressants. J'ai écrit une note à ce sujet (en anglais) : https://github.com/nono/cozy-desktop-experiments/blob/main/RFC/Interest.md.

    Au début, ça a l'air plutôt facile, on arrive facilement à faire un truc qui fonctionne en local. Puis, on le met entre les mains des utilisateurs, et on découvre plein de bugs. On les corrige, et on recommence. Et, après quelques itérations, on se rend compte que c'est un système distribué que l'on est en train d'écrire, et que faire un truc fiable dans ce domaine ne s'improvise pas. Mon principal regret est de ne pas avoir écrit un simulateur au début (c'est beaucoup plus compliqué à faire a posteriori quand la base de code commence à être grosse) : https://lobste.rs/s/igiolo/learning_build_distributed_systems#c_nlpl7r explique bien le principe.

    Je conseille aussi fortement la lecture de ces 2 articles de Dropbox, sur la refonte de leur client (en rust) :

    doit pouvoir être déployé sur des machines quelconques (Linux, Windows, MacOS)

    Bon courage ! Je vois que tu as commencé par Linux (tu parles d'inotify), c'est très bien, c'est l'OS le plus facile à mes yeux. Le système de fichiers est sensible à la casse, ce qui évite certains problèmes par exemple (HFS+ sur les anciens macOS fait de la normalisation unicode des chemins à l'aide d'un algorithme proche de NFD mais non standard, ça a nous a donné une tonne de bugs sur cozy-desktop).

    Pour Linux, il faut faire attention à ne pas utiliser le numéro d'inode comme un identifiant de fichier de manière trop strict. Il y a 2 pièges à ça :

    • quelques logiciels passent par un fichier temporaire quand on sauvegarde (genre vim ou libreoffice) : ils créent une copie du fichier avec la nouvelle version, puis quand ils ont fini d'écrire, ils suppriment l'original et déplacent la copie à l'emplacement de l'original => c'est le même fichier aux yeux de l'utilisateur, mais le numéro d'inode a changé

    • les systèmes de fichiers réutilisent assez facilement les numéros d'inode :

    $ echo foo > foo
    $ stat foo      
      File: foo
      Size: 4           Blocks: 8          IO Block: 4096   regular file
    Device: fd00h/64768d    Inode: 7870750     Links: 1
    Access: (0644/-rw-r--r--)  Uid: ( 1000/    nono)   Gid: ( 1000/    nono)
    Access: 2021-10-02 17:43:24.628613580 +0200
    Modify: 2021-10-02 17:44:07.714126187 +0200
    Change: 2021-10-02 17:44:07.714126187 +0200
     Birth: -
    $ echo bar > bar
    $ rm foo
    $ echo baz > baz 
    $ stat baz
      File: baz
      Size: 4           Blocks: 8          IO Block: 4096   regular file
    Device: fd00h/64768d    Inode: 7870750     Links: 1
    Access: (0644/-rw-r--r--)  Uid: ( 1000/    nono)   Gid: ( 1000/    nono)
    Access: 2021-10-02 17:44:28.994866193 +0200
    Modify: 2021-10-02 17:44:28.994866193 +0200
    Change: 2021-10-02 17:44:28.994866193 +0200

    foo et baz sont 2 fichiers différents, mais ils ont eu le même numéro d'inode (juste pas en même temps).

    Voilà, j'espère que ça donne quelques pistes pour améliorer la fiabilité du trsync.

    • [^] # Re: Retour d'expérience

      Posté par  . Évalué à 5. Dernière modification le 02/10/21 à 18:52.

      les systèmes de fichiers réutilisent assez facilement les numéros d'inode

      Oui. De plus, l'inode n'est unique qu'au sein d'un même système de fichier, donc si le dossier synchronisé contient deux points de montage, ce n'est pas bon.

      Pire, certains systèmes de fichiers ne garantissent pas l'unicité des inodes. Pour Btrfs, par exemple, l'inode n'est unique que par sous-volume (avec le Copy-on-write, les fichiers peuvent être partagés jusqu'à la modification… et d'ailleurs, la modification d'un fichier peut aussi le faire changer d'inode). Et une partition Btrfs peut être montée entièrement sur un unique point de montage, avec tous les sous-volumes dedans.

      Je suppose que c'est vrai aussi pour ZFS.

      Donc ça peut causer des bugs « intéressant » effectivement, et la solution de n'accepter de synchroniser des fichiers n'appartenant qu'à un seul point de montage n'est pas suffisante.

    • [^] # Re: Retour d'expérience

      Posté par  (site Web personnel) . Évalué à 6.

      Merci pour ce retour d'expérience ! Il me sera très précieux !

      J'ai évité d'utiliser le numéro d'inode : Initialement pour palier aux éventuels déplacements d'une partition vers une autre (ou dans le genre). Je me suis évité des problèmes on dirait :)

      J'ai effectivement constaté ce comportement (création d'un fichier intermédiaire puis renommage) et dû gérer le cas …

      J'espère que je tiendrais le coup ^

      Blog: http://blog.bux.fr, github: http://github.com/buxx

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.