Traduction automatique
Cette page a été traduite automatiquement par IA et peut contenir des erreurs. En cas de doute, référez-vous à la source anglaise.
Synchronisation incrémentielle¶
pplx-export batch est conçu pour être exécuté fréquemment : chaque exécution exporte uniquement ce qui est nouveau ou modifié, comble les lacunes laissées par des exécutions interrompues et ne retouche jamais les fils que la plateforme a déjà retirés. La source unique de vérité pour « ce qui a été exporté » est index/batch_state.json (BatchState, pplx_export/core/state.py:63), mise à jour après chaque fil — il n'y a pas de copie fantôme séparée.
a. Prérequis et utilisation de base¶
pplx-export index --account alice # refresh index/library_alice.json first
pplx-export batch --account alice # incremental export (early stop, resumable)
batch refuse de s'exécuter sans l'index (pplx_export/commands/batch_cmd.py:79-81). --limit N et --mode <mode> filtrent les lignes de l'index avant la planification ; les lignes sans entryUUID sont ignorées avec un avertissement au lieu de faire échouer l'exécution (batch_cmd.py:95-100).
b. Comment fonctionne le plan incrémentiel¶
- Tri. Les lignes de l'index sont triées par
lastUpdated, les plus récentes en premier (batch_cmd.py:89). Les nouvelles conversations et les anciennes reprises (dontlastUpdatedvient de les remonter) se trouvent toutes en haut — cet ordre est ce qui rend l'arrêt précoce sûr. - Classification.
plan_incremental(pplx_export/hooks/incremental.py:36-87) — une fonction pure partagée parbatchetschedule— attribue à chaque ligne exactement une action :
| action | condition | ce que fait le lot |
|---|---|---|
new |
uuid jamais vu dans batch_state |
exporter |
updated |
lastUpdated diffère de la valeur enregistrée, ou --force |
ré-exporter |
done |
statut ok et lastUpdated inchangé |
ignorer |
expired |
la plateforme a retourné ENTRY_EXPIRED lors d'une tentative précédente |
ignorer — terminal, jamais réessayé |
deleted |
sync-deleted a confirmé une suppression distante |
ignorer — terminal, jamais réessayé |
- Arrêt précoce. Par défaut (ni
--fullni--force), la plus longue séquence finale d'entrées terminales (done/expired/deleted) est supprimée en bloc et comptée commen_stopped(incremental.py:83-87). Comme la liste est triée des plus récentes aux plus anciennes, tout ce qui se trouve en dessous d'une entrée inchangée est nécessairement plus ancien et inchangé aussi — continuer à analyser ne ferait que perdre du temps.
flowchart TD
IDX["library index rows<br/>sorted by lastUpdated, newest first"] --> PLAN["plan_incremental"]
PLAN --> NEW["new → export"]
PLAN --> UPD["updated → re-export"]
PLAN --> DONE["done → skip"]
PLAN --> TERM["expired / deleted → skip (terminal)"]
DONE --> STOP["early stop:<br/>trailing terminal run trimmed"]
TERM --> STOP
- Exécution. Chaque fil exporté est marqué immédiatement (
mark_ok/mark_error/mark_expired/mark_deleted) et le fichier d'état est sauvegardé après chaque élément (batch_cmd.py:154-201) ; unKeyboardInterruptsauvegarde également avant la propagation (batch_cmd.py:158-161). Les écritures sont atomiques — fichier temporaire plusos.replace(state.py:145-152) — donc une exécution interrompue ne laisse jamais de JSON tronqué.
c. Comblement des lacunes après des exécutions interrompues¶
L'arrêt précoce n'enterre jamais une lacune. Les fils qui ont échoué (statut error) ou qui n'ont jamais été atteints se trouvent au-dessus du suffixe terminal, donc la prochaine exécution les replanifie comme updated / new et les exporte avant d'atteindre le point d'arrêt précoce (incremental.py:12-14, batch_cmd.py:206-208). Combiné avec les sauvegardes d'état par élément, un lot peut être interrompu à tout moment et simplement relancé.
Si batch_state.json lui-même est corrompu, il n'est pas silencieusement vidé : l'original est renommé en batch_state.json.corrupt-<timestamp> afin que les états terminaux enregistrés ne soient pas perdus et inutilement réessayés (state.py:68-81).
d. --full et --force¶
| drapeau | effet | états terminaux | quand l'utiliser |
|---|---|---|---|
| (par défaut) | arrêt précoce sur la séquence terminale | ignorés | chaque exécution régulière / planifiée |
--full |
analyse complète, pas d'arrêt précoce ; les fils inchangés sont toujours ignorés comme done |
ignorés | filet de sécurité périodique, ou quand des lacunes d'archive sont suspectées |
--force |
ré-exporter tout, même les fils inchangés | toujours exclus — jamais réessayés | après des corrections de pipeline qui doivent récupérer les données brutes |
Les états terminaux sont exclus de --force par conception : réessayer un fil expiré ou supprimé à distance ne fait que gaspiller des requêtes et du budget de backoff (batch_cmd.py:120-127).
Voir aussi status : un rapport sans réseau de l'état du compte et du plan de changement calculé avec la même sémantique plan_incremental (new/updated/compteur d'arrêt précoce).
La comparaison lastUpdated normalise les zéros de fin dans la partie des fractions de seconde (.18033Z est égal à .180330Z ; state.py:23-55), car la plateforme les supprime parfois — une comparaison exacte de chaînes jugerait à tort « modifié » et provoquerait des exportations en double.
e. États terminaux : expired et deleted¶
expired |
deleted |
|
|---|---|---|
| signification | la plateforme a purgé le fil (fenêtre de rétention ~3 mois) ; la tentative d'exportation a retourné ENTRY_EXPIRED |
suppression par l'utilisateur/à distance, confirmée par sync-deleted |
| enregistré par | batch lui-même (mark_expired, state.py:131-134) |
pplx-export sync-deleted --online (mark_deleted, state.py:136-143) |
| réessayé ? | jamais — même pas avec --force |
jamais — même pas avec --force |
| preuve | la réponse ENTRY_EXPIRED |
champ note : absence dans l'index + GET /rest/thread/<uuid> → ENTRY_DELETED / ENTRY_EXPIRED / HTTP 404 |
e.1 sync-deleted : confirmation des suppressions distantes¶
pplx-export sync-deleted --account alice # offline dry-run: list candidates only
pplx-export sync-deleted --account alice --online # confirm each candidate online
- Candidats (hors ligne, zéro réseau). Tout fil avec le statut
okdansbatch_statequi est absent de l'unionentryUUIDde tous les index de compteindex/library_*.jsonest un candidat suspect de suppression distante (pplx_export/commands/sync_deleted_cmd.py:148-212). L'union sur tous les comptes est nécessaire : un fil appartenant àbobmais exporté paralicevia un espace partagé n'apparaît jamais dans l'index dealicelui-même — une différence sur un seul compte produirait des faux positifs pour tout cet ensemble. Lorsqu'aucun index utilisable n'existe du tout, chaque candidat est ignoré en toute sécurité avec la raison enregistrée. - Simulation par défaut. Sans
--online, la commande liste uniquement les candidats — pas de réseau, pas de modifications de fichiers. - Confirmation
--online. Chaque candidat est vérifié avecGET /rest/thread/<uuid>, en utilisant le compteexport_viadu candidat depuisthread.json(le cookie change automatiquement) :
| résultat | issue |
|---|---|
ENTRY_DELETED / ENTRY_EXPIRED / HTTP 404 |
confirmé : batch_state marque terminal deleted (le note enregistre la raison), et chaque thread.json de ce fil reçoit un horodatage remote_deleted à sa place |
| le fil existe toujours | faux positif : signalé tel quel (l'index n'est peut-être pas entièrement actualisé — relancez index et vérifiez à nouveau), rien n'a changé |
| 5xx / erreur réseau | aucun changement d'état ; le candidat est laissé pour le prochain tour |
| 3 erreurs 401/403 consécutives | abandon rapide — un cookie expiré ne peut pas se guérir lui-même, et continuer marquerait à tort des fils actifs (sync_deleted_cmd.py:333-337) |
Les marques confirmées sont persistées par élément, donc une exécution --online interrompue ne perd rien et les relances sont idempotentes (sync_deleted_cmd.py:254-256).
f. Le principe de la pierre tombale¶
Les archives locales ne sont jamais supprimées
Cette archive est la sauvegarde de référence des conversations exportées.
sync-deleted identifie et marque (pierre tombale) uniquement : il ne supprime ni ne déplace jamais de fichier d'archive. La confirmation change exactement deux choses — le statut batch_state et une clé de marqueur dans thread.json :
"remote_deleted": "2026-07-23T10:20:30Z"
Le tampon est idempotent : une clé remote_deleted existante n'est ni réécrite ni écrasée (sync_deleted_cmd.py:215-244).
g. Idempotence et régénération hors ligne¶
- Relancer
batchsur un index inchangé n'exporte rien : chaque ligne est classée commedoneet l'exécution s'arrête au point d'arrêt précoce. Les écritures d'état sont atomiques, les marques sont par fil, et les suppressions reconfirmées ne dupliquent jamais le tamponremote_deleted. - L'archive conserve les charges utiles brutes de l'API (
raw_entries.json/raw_blocks.json), donc les fichiers rendus peuvent être régénérés à tout moment sans accès réseau :
pplx-export re-render # rebuild conversation.md + turns/ everywhere
pplx-export re-render --dry-run # only list the thread directories
pplx-export re-render --thread-json # also sync interruptions / answer_variants keys
re-render réanalyse le JSON brut avec le moteur de rendu actuel (pplx_export/commands/rerender_cmd.py:105-190) : conversation.md et turns/turn_*.md sont réécrits, les fichiers de tour obsolètes numérotés au-dessus du nombre de tours actuel sont supprimés, et les sources, ressources, report.md et thread.json sont laissés intacts. C'est ainsi que les corrections du moteur de rendu se déploient sur l'ensemble de l'archive sans une seule requête.
h. Voir aussi¶
- pplx-export.md — référence complète de la commande
batch(--mode,--limit, délais) - maintenance-commands.md —
sync-deleted,re-renderet les commandes de rattrapage - archive-layout.md — où se trouvent
batch_state.jsonetthread.json - rate-limiting.md — cadencement entre les fils, backoff, abandon rapide sur erreur d'authentification
- ../architecture/export-pipeline.md — le pipeline d'exportation complet
- ../architecture/offline-operations.md — le pipeline de régénération hors ligne en détail
- ../architecture/rate-limiting-errors.md — taxonomie des erreurs et gestion des états terminaux