312 lines
10 KiB
Markdown
312 lines
10 KiB
Markdown
# Base de données projet Lardon3D
|
|
|
|
## Vision
|
|
|
|
La base de données projet stocke les métadonnées de reconstruction et les relations entre les entités. Elle est conçue pour être légère, persistante et permettre la reprise après interruption.
|
|
|
|
## Structure conceptuelle
|
|
|
|
### Entités principales
|
|
|
|
#### Project
|
|
- Identifiant unique
|
|
- Nom et description
|
|
- Date de création
|
|
- Configuration
|
|
- Chemins des répertoires
|
|
|
|
#### Scan Set
|
|
- Identifiant unique
|
|
- Nom de l'acquisition
|
|
- Date
|
|
- Provenance
|
|
- État de traitement
|
|
|
|
#### Image
|
|
- Identifiant unique
|
|
- Chemin du fichier
|
|
- Métadonnées EXIF
|
|
- État de traitement
|
|
- Appartenance aux scan sets
|
|
|
|
#### Feature Set
|
|
- Identifiant unique
|
|
- Type de descripteur
|
|
- Paramètres
|
|
- Chemin des données
|
|
|
|
#### Visual Signature
|
|
- Identifiant unique
|
|
- Type d'index
|
|
- Paramètres
|
|
- Chemin des données
|
|
|
|
#### Candidate Pair
|
|
- Identifiant unique
|
|
- Image source
|
|
- Image cible
|
|
- Score de similarité
|
|
- Source (visuelle, temporelle, etc.)
|
|
|
|
#### Verified Pair
|
|
- Identifiant unique
|
|
- Candidate pair source
|
|
- Statut (validée, rejetée)
|
|
- Métriques
|
|
|
|
#### Track
|
|
- Identifiant unique
|
|
- Observations
|
|
- Point 3D associé
|
|
- Qualité
|
|
|
|
#### Observation
|
|
- Identifiant unique
|
|
- Image
|
|
- Position 2D
|
|
- Descripteur
|
|
- Track parent
|
|
|
|
#### Camera
|
|
- Identifiant unique
|
|
- Modèle
|
|
- Paramètres intrinsèques
|
|
- Distorsion
|
|
|
|
#### Pose
|
|
- Identifiant unique
|
|
- Camera
|
|
- Translation
|
|
- Rotation
|
|
- Qualité
|
|
|
|
#### Point3D
|
|
- Identifiant unique
|
|
- Position
|
|
- Couleur
|
|
- Qualité
|
|
- Observations
|
|
|
|
#### Reconstruction Layer
|
|
- Identifiant unique
|
|
- Type (sparse, dense, mesh, etc.)
|
|
- Provenance
|
|
- Transformations
|
|
- Qualité
|
|
- Chemin des données
|
|
|
|
#### Measurement
|
|
- Identifiant unique
|
|
- Type
|
|
- Valeur
|
|
- Incertitude
|
|
- Cible géométrique
|
|
|
|
#### Document Source
|
|
- Identifiant unique
|
|
- Type (plan, croquis, etc.)
|
|
- Chemin
|
|
- Métadonnées
|
|
|
|
#### Geometric Constraint
|
|
- Identifiant unique
|
|
- Type
|
|
- Paramètres
|
|
- Sources
|
|
- Poids
|
|
|
|
#### Artifact
|
|
- Identifiant unique
|
|
- Type
|
|
- État (temporaire, publié)
|
|
- Chemin
|
|
- Métadonnées
|
|
|
|
#### Checkpoint
|
|
- Identifiant unique
|
|
- État du pipeline
|
|
- Métadonnées
|
|
- Date
|
|
|
|
## Relations
|
|
|
|
- Project → Scan Set (1:N)
|
|
- Scan Set → Image (N:M)
|
|
- Image → Feature Set (1:N)
|
|
- Image → Visual Signature (1:N)
|
|
- Candidate Pair → Image (2)
|
|
- Verified Pair → Candidate Pair (1)
|
|
- Track → Observation (N:M)
|
|
- Observation → Image (1)
|
|
- Observation → Point3D (N:1)
|
|
- Camera → Pose (1:N)
|
|
- Pose → Reconstruction Layer (N:M)
|
|
- Reconstruction Layer → Artifact (1:N)
|
|
- Measurement → Point3D (N:1)
|
|
- Document Source → Geometric Constraint (N:M)
|
|
- Geometric Constraint → Point3D (N:M)
|
|
- Artifact → Checkpoint (N:1)
|
|
|
|
## Invariants
|
|
|
|
- Chaque entité a un identifiant unique stable
|
|
- Les relations sont explicitement définies
|
|
- Les artefacts partiels ne sont jamais considérés comme valides
|
|
- La reprise commence à la dernière frontière connue
|
|
|
|
## Frontière avec les checkpoints de tâche
|
|
|
|
Le modèle durable v1 et son codec fichier sont implémentés indépendamment du
|
|
stockage. La base réutilise les mêmes règles de normalisation et de
|
|
validation ; elle ne stockera jamais les objets pthread, callbacks, pointeurs,
|
|
contrats ou réservations. Le fichier par tâche est une fondation, pas une
|
|
Project Database miniature.
|
|
|
|
La stratégie v1 retient un résumé logique interrogable dans SQLite et une
|
|
référence vers le fichier checkpoint. Le fichier checkpoint validé reste la
|
|
source complète pour `lardon3d_task_restore()` ; la DB seule ne reconstruit
|
|
jamais une tâche. Un écart ou un fichier invalide interdit la reprise.
|
|
|
|
## Schéma v3 implémenté
|
|
|
|
- `metadata(key PRIMARY KEY, value)` contient `schema_version=3` et
|
|
`next_task_id`, prochain ID durable allouable.
|
|
- `project(singleton=1, stable_id UNIQUE, name, created_at, updated_at)` décrit
|
|
l'unique identité logique de la DB.
|
|
- `tasks(task_id PRIMARY KEY, name, task_kind, task_kind_version, saved_state, recovery_state, progress,
|
|
sequence_count, started_sec/nsec, finished_sec/nsec, updated_at)` contient le
|
|
résumé durable. Les IDs v1 sont compris entre 1 et `INT64_MAX`.
|
|
- `checkpoints(task_id PRIMARY KEY REFERENCES tasks ON DELETE CASCADE, path,
|
|
format_version, durability, updated_at)` représente `DURABLE` ou
|
|
`PUBLISHED_NOT_DURABLE`.
|
|
- `artifacts(artifact_id PRIMARY KEY, kind, path, state, size_bytes,
|
|
producer_task_id REFERENCES tasks, created_at, updated_at)` inventorie des
|
|
fichiers externes. Les états v1 sont `STAGED` et `READY`.
|
|
- `image_import_tasks(task_id PRIMARY KEY REFERENCES tasks ON DELETE CASCADE,
|
|
source_path)` conserve l'unique paramètre métier v1 de `import.images`.
|
|
|
|
Les indexes portent uniquement sur `tasks(recovery_state, task_id)`,
|
|
`artifacts(state, artifact_id)` et `artifacts(producer_task_id)`.
|
|
|
|
## Ouverture et migrations
|
|
|
|
Une DB vide reçoit directement le schéma v3 dans une transaction
|
|
`BEGIN IMMEDIATE`. Une DB v1 reçoit transactionnellement les colonnes nullable
|
|
`task_kind` et `task_kind_version`, puis les migrations v2→v3. Les anciennes lignes restent
|
|
`NULL/NULL`, sans type inventé et sans perte des projets, tâches, checkpoints ou
|
|
artefacts. Une interruption ou erreur provoque un rollback complet. Une DB v2
|
|
est migrée vers v3 ; une DB v3 est validée puis ouverte. Une version future est refusée et une DB contenant
|
|
des tables sans métadonnée de version est considérée corrompue. La fonction
|
|
interne de migration ne connaît que `0 → 3`, `1 → 2 → 3` et `2 → 3`.
|
|
|
|
Migration v1→v2 exacte, exécutée entre `BEGIN IMMEDIATE` et `COMMIT` :
|
|
|
|
```sql
|
|
ALTER TABLE tasks ADD COLUMN task_kind TEXT;
|
|
ALTER TABLE tasks ADD COLUMN task_kind_version INTEGER
|
|
CHECK(task_kind_version IS NULL OR task_kind_version > 0);
|
|
UPDATE metadata SET value=2
|
|
WHERE key='schema_version' AND value=1;
|
|
```
|
|
|
|
Migration v2→v3 exacte, exécutée entre `BEGIN IMMEDIATE` et `COMMIT` :
|
|
|
|
```sql
|
|
CREATE TABLE image_import_tasks(
|
|
task_id INTEGER PRIMARY KEY REFERENCES tasks(task_id) ON DELETE CASCADE,
|
|
source_path TEXT NOT NULL
|
|
);
|
|
INSERT INTO metadata(key,value)
|
|
VALUES('next_task_id',(
|
|
SELECT CASE
|
|
WHEN COALESCE(MAX(task_id),0)>=9223372036854775807 THEN 0
|
|
ELSE COALESCE(MAX(task_id),0)+1
|
|
END FROM tasks
|
|
));
|
|
UPDATE metadata SET value=3
|
|
WHERE key='schema_version' AND value=2;
|
|
```
|
|
|
|
Configuration v3 : `foreign_keys=ON`, `journal_mode=DELETE`,
|
|
`synchronous=FULL`, `busy_timeout=5000`. Le mode DELETE convient au propriétaire
|
|
unique actuel, évite les fichiers WAL/SHM durables et conserve la synchronisation
|
|
forte. Le timeout borne l'attente d'un verrou externe à cinq secondes.
|
|
|
|
## Concurrence et ownership
|
|
|
|
Une connexion opaque est sérialisée par un mutex interne. Chaque opération
|
|
composée possède sa transaction entière ; aucune transaction publique ne peut
|
|
rester ouverte entre deux appels. Aucune I/O d'artefact n'a lieu sous le mutex :
|
|
le module confirme que le fichier publié et validé par l'appelant est régulier
|
|
avant la mise à jour `READY`. Fermer la DB pendant un
|
|
appel concurrent est interdit au propriétaire.
|
|
|
|
Les records et chaînes sont copiés dans des buffers fournis par l'appelant ;
|
|
aucun pointeur SQLite n'en sort. Tous les statements sont finalisés dans
|
|
l'appel. La liste de reprise utilise des pages fournies par l'appelant, limitées
|
|
à 256 entrées. Elle ne retourne que les tâches normalisées `PENDING` possédant
|
|
une référence checkpoint ; le fichier doit encore être chargé et validé.
|
|
|
|
## Branchement au projet
|
|
|
|
`Lardon3DAppState` est l'instance projet runtime actuelle et possède exactement
|
|
une `Lardon3DProjectDb *` pendant que `project_loaded` est vrai. La DB canonique
|
|
est `<project_root>/project.db`. Elle est ouverte à la création/ouverture du
|
|
projet et fermée une seule fois par `lardon3d_project_close()`. À l'arrêt de
|
|
l'application, la task queue est arrêtée avant la fermeture du projet et de sa
|
|
DB. Une fermeture concurrente à un appel projet/DB est interdite au propriétaire.
|
|
|
|
`project.ini` v2 contient `name`, `stable_id` hexadécimal sur 128 bits et
|
|
`version=2`. La même identité est enregistrée dans la table `project`. Toute
|
|
divergence est une erreur. Un INI v1 sans identité adopte l'identité d'une DB
|
|
existante ; sans DB, une identité est générée une seule fois puis l'INI est
|
|
migré atomiquement avant de devenir la référence des ouvertures suivantes. Une
|
|
DB existante sans ligne projet ne peut être initialisée que si l'INI possède
|
|
déjà son identité.
|
|
|
|
Les checkpoints sont référencés par chemins relatifs portables :
|
|
`.lardon3d/checkpoints/<task_id>.chk`. L'inventaire projet pagine les tâches DB,
|
|
résout ce chemin sous la racine, charge le checkpoint et vérifie la cohérence du
|
|
snapshot avec le résumé DB.
|
|
|
|
Après copie du record hors mutex SQLite, l'inventaire consulte la registry. Il
|
|
distingue `LEGACY_UNTYPED`, `UNKNOWN_TASK_KIND` et
|
|
`UNSUPPORTED_TASK_KIND_VERSION`. Aucun reconstructeur métier n'est appelé sous
|
|
le mutex DB. Un upsert ne peut pas changer le couple kind/version d'un task ID.
|
|
|
|
À l'ouverture, le projet lit des pages de 8 dans l'ordre croissant des task
|
|
IDs. Chaque record est copié hors mutex DB avant reconstruction et enqueue. Une
|
|
fenêtre pleine interrompt le scan sans modifier les tâches restantes. Le résumé
|
|
borné expose `inspected`, `resumed`, `skipped`, `failed`, le nombre de
|
|
checkpoints `PUBLISHED_NOT_DURABLE` repris et la saturation éventuelle.
|
|
|
|
Les erreurs d'ouverture/migration, de schéma ou d'identité restent fatales.
|
|
Les erreurs propres à une tâche — legacy, kind inconnu/futur, checkpoint
|
|
absent/invalide/futur, source indisponible ou reconstruction — sont non fatales.
|
|
Un `BUSY` après le timeout SQLite arrête le scan sans boucle et laisse le projet
|
|
ouvert.
|
|
|
|
## Statut
|
|
|
|
**IMPLEMENTED** — SQLite système, schéma v3 et migrations v1→v2→v3, identité
|
|
projet, transactions tâche+checkpoint, pagination de reprise et artefacts
|
|
génériques.
|
|
|
|
**IMPLEMENTED** — ouverture/fermeture avec le projet, identité INI/DB cohérente,
|
|
publication de checkpoints par le projet et inventaire de reprise validé.
|
|
|
|
**IMPLEMENTED** — kinds persistants, classification par registry et
|
|
reconstruction explicite testée hors scheduler.
|
|
|
|
**IMPLEMENTED** — allocation transactionnelle de task IDs, paramètres
|
|
immuables de `import.images` et reconstruction production explicite.
|
|
|
|
**IMPLEMENTED** — reprise automatique sélective, pagination de 8, ordre par ID,
|
|
fenêtre de queue non bloquante et résumé consultable.
|
|
|
|
**NOT_YET_WIRED** — autosave à toutes les transitions, retry UI des sources
|
|
indisponibles et réconciliation des checkpoints orphelins, ScanSet
|
|
et catalogue image persistants, Feature Store et Visual Index.
|
|
|
|
**PLANNED** — migrations v4+, dépendances d'artefacts, graphe géométrique et
|
|
reconstruction incrémentale.
|