Aller au contenu

Modes de runtime

Le bloc runtime: du manifest déclare comment le code de la fonction s’exécute. Trois modes sont supportés, distingués par le discriminant runtime.kind :

kindCas d’usageCoût de buildLangage
python (mode A)Python pur, sans dépendance nativeNul — c’est MecaPy qui construitPython uniquement
dockerfile (mode B)Dépendances natives, chaîne d’outils particulière (Code_Aster, OpenFOAM, …)Build au premier déploiementAu choix
image (mode C)Image déjà publiée dans un registreNul — l’image est tirée telle quelleAu choix

Les trois modes partagent le même contrat de runtime — même arborescence du workspace, mêmes variables d’environnement, mêmes sémantiques de progression / erreur / annulation. Le mode change seulement qui construit l’image et quel point d’entrée le worker invoque.

Le mode par défaut. Vous fournissez handler.py (ou un paquet Python) et mecapy.yml. MecaPy construit une image Python légère, y copie votre code, et l’exécute via un runner géré qui prend en charge toute l’E/S.

name: bolt-sizing
runtime:
kind: python
version: "3.12"
requirements: false # passez à true pour installer requirements.txt au build
functions:
sizing:
handler: bolts:size
resources:
recommended: { cpu: 1, memory_mb: 512 }
timeout: 60
def size(diameter_mm: float, load_n: float) -> dict:
return {"stress_mpa": load_n / (3.14 * (diameter_mm / 2) ** 2)}

La signature de la fonction nourrit l’introspection pour le formulaire d’exécution (AutoForm). Pour le typage côté workflow, déclarez les ports inputs: / outputs: — voir ports d’E/S typés.

Quand choisir ce mode. Python pur avec dépendances scientifiques (NumPy / SciPy / Pandas / vos propres modules pur-Python). 90 % des fonctions de dimensionnement mécanique rentrent ici.

Vous fournissez un Dockerfile (et le contexte de build nécessaire) et mecapy.yml. MecaPy construit l’image au premier déploiement et la met en cache pour les runs suivants.

name: code-aster-thermal
runtime:
kind: dockerfile
dockerfile: ./Dockerfile
context: . # relatif à la racine du dépôt ; par défaut "."
functions:
thermal-analysis:
entrypoint: ["/usr/bin/run-aster.sh", "--quick"]
resources:
recommended: { cpu: 4, memory_mb: 8192 }
timeout: 1800
inputs:
mesh: { type: File[mmed,med] }
thermal_load: { type: Numeric }
outputs:
max_stress: { type: Stress }

entrypoint: est la commande que le worker lance après avoir préparé /workspace/in/. Votre script lit in/data.json + in/files/ et écrit out/data.json + out/files/ selon le contrat de runtime.

Quand choisir ce mode. Vous avez besoin d’une chaîne d’outils non Python, d’un solveur natif compilé en C/C++/Fortran, de MPI, de GPU, ou d’un paquet système absent de l’image de base du mode A.

Vous pointez vers une image déjà publiée sur un registre — docker.io, GitHub Container Registry, votre registre privé, etc. MecaPy la tire une fois et l’exécute.

name: code-aster-mvp
runtime:
kind: image
image: ghcr.io/myorg/code-aster:15.4 # référence complète avec tag
functions:
thermal-analysis:
entrypoint: ["/opt/aster/run.sh"]
resources:
recommended: { cpu: 4, memory_mb: 8192 }
timeout: 1800
inputs:
mesh: { type: File[mmed,med] }
thermal_load: { type: Numeric }
outputs:
max_stress: { type: Stress }

L’image doit déjà respecter le contrat — lire in/, écrire out/. Aucun code MecaPy n’est injecté à l’exécution dans ce mode.

Quand choisir ce mode. Vous publiez déjà l’image ailleurs (CI interne, distribution d’un fournisseur) et vous ne voulez pas maintenir le contexte de build dans le manifest.

En modes B/C, chaque fonction déclare son propre entrypoint: — la même image peut héberger plusieurs commandes :

runtime:
kind: image
image: ghcr.io/myorg/solver:latest
functions:
thermal:
entrypoint: ["/opt/run.sh", "--mode=thermal"]
mechanical:
entrypoint: ["/opt/run.sh", "--mode=mechanical"]

L’image est tirée (ou construite) une seule fois ; les deux fonctions la réutilisent avec des arguments différents au moment de l’exécution.

En mode A, l’introspection lit la signature Python pour générer le formulaire d’exécution. Les modes B/C n’ont pas de signature à lire, donc les ports d’entrée et de sortie doivent être déclarés explicitement dans inputs: / outputs:, en utilisant les types du catalogue canonique :

functions:
thermal-analysis:
entrypoint: ["/usr/bin/run-aster.sh"]
inputs:
mesh_file:
type: File[mmed,med]
description: "Maillage code_aster d'entrée."
thermal_load:
type: Numeric
description: "Charge thermique appliquée (W/m²)."
outputs:
max_stress:
type: Stress
description: "Contrainte maximale calculée."

Ces ports pilotent le typage de l’éditeur de workflow et le formulaire d’exécution. Ils déterminent aussi ce qui finit dans in/data.json (scalaires) versus in/files/ (fichiers). Voir ports d’E/S typés pour la grammaire complète.

Les trois modes sont câblés de bout en bout : la route de déploiement accepte toute valeur de runtime.kind, persiste les champs propres au mode (handler versus entrypoint, chemin du Dockerfile, référence d’image), et le worker sait construire / tirer puis exécuter l’image résultante. Les workflows composent des nœuds de tous les modes indifféremment.

Pour les modes B et C, le script d’entrée est responsable du contrat de runtime. Voir recettes pour les modes B et C pour des patterns Bash copiables couvrant entrées, sorties, progression, erreurs et arrêt gracieux sur SIGTERM.