Chaîne de traitements externes
Source: tutorial/09_process_pipeline See in Playground
Lit un fichier, transmet son contenu à la commande système sort, puis écrit le résultat trié. Mélodium orchestre le sous-processus et ses flux d’entrée/sortie ; le tri lui-même est entièrement effectué par sort.
Exécution
cd tutorial/09_process_pipeline
melodium run Compo.toml --input_file fruits.txtCela transforme un fichier contenant banana, apple, cherry, date et elderberry en un fichier sorted.txt trié par ordre alphabétique.
Optionnel : ajoutez --api-report et un jeton d’API (MELODIUM_API_TOKEN) pour voir la trace complète de cette exécution sur Cadence.CI .
Fonctionnement
Il n’y a aucun modèle personnalisé ici : spawnOnce est un traitement pratique qui obtient lui-même un exécuteur local. Les octets du fichier sont connectés directement à l’entrée standard (stdin) du sous-processus, et sa sortie standard (stdout) ainsi que sa sortie d’erreur (stderr) sont traitées comme n’importe quel autre flux d’octets :
treatment main(
const input_file: string = "fruits.txt",
const output: string = "sorted.txt"
) {
startup()
read: readLocal(path=input_file)
startup.trigger -> read.trigger
proc: spawnOnce(command=|command("sort", []))
read.data -> proc.stdin
startup.trigger -> proc.launch
procFailed: logErrorMessage(label="process", message="failed to spawn `sort`")
procError: logError(label="process")
proc.failed -> procFailed.trigger
proc.error -> procError.message
exitCode: unwrapOr<i32>(default=-1)
logExitCode: logDataInfo<i32>(label="exit-code")
logExit: logInfoMessage(label="process", message="sort finished")
proc.exit -> exitCode.option,value -> logExitCode.data
proc.completed -> logExit.trigger
stderrText: decode()
stderrLog: logErrors(label="sort-stderr")
proc.stderr -> stderrText.data
stderrText.text -> stderrLog.messages
stdoutText: decode()
proc.stdout -> stdoutText.data
write: writeTextLocal(path=output)
logDone: logInfoMessage(label="process", message="sorted output written")
stdoutText.text -> write.text
write.finished -> logDone.trigger
}Le flux de données fait traverser le fichier directement à travers le sous-processus puis le renvoie vers le disque :
read.data (les octets du fichier) est connecté directement à proc.stdin ; sort commence à lire dès que des octets arrivent, avant même que la lecture du fichier soit terminée. Il n’y a pas d’étape “lire tout le fichier, puis démarrer le sous-processus”, le sous-processus n’est jamais qu’un traitement de plus avec des ports de flux.
Un sous-processus est traité exactement comme n’importe quel autre traitement à ports de flux : stdin, stdout et stderr sont des Stream<byte>, tout comme un corps HTTP ou le contenu d’un fichier, si bien que tous les idiomes déjà employés pour le décodage et l’encodage s’appliquent sans changement. |command(name, arguments) construit une valeur Command à partir d’un nom d’exécutable et d’un vecteur d’arguments, vide ici.
proc.exit est un Block<Option<i32>> (none si le processus a été tué par un signal plutôt que de se terminer normalement) ; unwrapOr fournit une valeur de repli. À noter qu’il s’agit ici de la variante bloc de unwrapOr (celle de std/ops/option/block), et non de la variante flux utilisée ailleurs dans le tutoriel : les deux font le même travail sur des types de ports différents, et se tromper de variante est une erreur de type que melodium check détecte immédiatement.
stdout et stderr sont tous deux décodés puis journalisés ou écrits directement. Une exécution réussie sans rien sur stderr ne produit strictement aucun élément sur stderrText.text, si bien que stderrLog ne journalise rien, pas même une ligne vide.
Dépendances
[dependencies]
std = "0.10.3" # flux de base, journalisation, structures de données
fs = "0.10.3" # lecture/écriture de fichiers locaux
process = "0.10.3" # exécution de processus externes
encoding = "0.10.3" # encodage / décodage UTF-8