Aller au contenu

Runtime Resolver

Introduction

Le Runtime Resolver est le moteur central du Workflow Runtime qui traite les variables lors de l'exécution du workflow. Il gère le cycle de vie des variables en enregistrant les outputs, en résolvant les paramètres et en effectuant les castages de types.


Aperçu du Flux d'Exécution

flowchart TD
    Start["1. Noeud START<br/>Variables declarees<br/>Dictionnaire initialise"] 

    Task1["2. TACHE 1 EXECUTER<br/>Produit un output<br/>Exemple: cmd_error_output"]

    Register["3. ENREGISTREMENT<br/>Output stocke en dictionnaire<br/>VAR stocke valeur"]

    Task2["4. TACHE 2 ATTEND<br/>Contient des parametres<br/>avec variables"]

    Resolve["5. RESOLUTION<br/>Scanne parametres pour variables<br/>Remplace par valeurs dictionnaire"]

    Cast["6. CASTING<br/>Convertit String vers Type cible<br/>String vers Double, JSON, etc."]

    Execute["7. TACHE 2 EXECUTER<br/>Avec valeurs resolues et castees"]

    End["8. Noeud END<br/>Dictionnaire persiste"]

    Start --> Task1
    Task1 --> Register
    Register --> Task2
    Task2 --> Resolve
    Resolve --> Cast
    Cast --> Execute
    Execute --> End

    style Start fill:#e3f2fd
    style Task1 fill:#f3e5f5
    style Register fill:#fff9c4
    style Task2 fill:#f3e5f5
    style Resolve fill:#fff9c4
    style Cast fill:#fff9c4
    style Execute fill:#f3e5f5
    style End fill:#c8e6c9

Étape 1 : Déclaration des Variables et Initialisation du Dictionnaire

Au nœud START, les variables sont déclarées et le dictionnaire runtime est initialisé.

{
  "Start": [
    {
      "id": "0",
      "variables": [
        {
          "variableName": "$TIME_OFFSET",
          "variableValue": "0",
          "is_kpi": false
        },
        {
          "variableName": "$LATITUDE",
          "variableValue": "0.0",
          "is_kpi": true
        },
        {
          "variableName": "$API_RESPONSE",
          "variableValue": "{}",
          "is_kpi": false
        }
      ]
    }
  ]
}

Dictionnaire Runtime Initial :

{
  "$TIME_OFFSET": "0",
  "$LATITUDE": "0.0",
  "$API_RESPONSE": "{}"
}


Étape 2 : Exécution de la Tâche et Enregistrement de l'Output

Quand une tâche s'exécute et produit un output, le Runtime Resolver enregistre cet output dans le dictionnaire.

Exemple : Tâche NtpSync

{
  "NtpSync": [
    {
      "id": "1",
      "ntp_server": "time.google.com",
      "ntp_port": 123,
      "ntp_timeout": 5000,
      "ntp_offset_output": "$TIME_OFFSET"
    }
  ]
}

Timeline d'Exécution

sequenceDiagram
    participant Task as Tache 1<br/>(NtpSync)
    participant Resolver as Runtime<br/>Resolver
    participant Dict as Dictionnaire<br/>Runtime

    Task->>Task: Interroge serveur NTP<br/>time.google.com
    Task->>Task: Reçoit réponse temps
    Task->>Resolver: Output produit<br/>Offset: '125'
    Resolver->>Dict: Enregistre output<br/>$TIME_OFFSET = '125'
    Dict->>Dict: Mise à jour dictionnaire
    Resolver-->>Task: ✅ Output enregistré

    Note over Dict: {<br/>  "$TIME_OFFSET": "125",<br/>  "$LATITUDE": "0.0",<br/>  "$API_RESPONSE": "{}"<br/>}

État du Dictionnaire Après Tâche 1 :

{
  "$TIME_OFFSET": "125",
  "$LATITUDE": "0.0",
  "$API_RESPONSE": "{}"
}


Étape 3 : Résolution des Paramètres

Avant que Tâche 2 s'exécute, le Runtime Resolver scanne tous les paramètres pour identifier les variables (chaînes commençant par $) et les remplace par les valeurs du dictionnaire.

Exemple : Tâche CompareNumber

{
  "CompareNumber": [
    {
      "id": "2",
      "num_x": "$TIME_OFFSET",
      "num_y": "200",
      "compare_type": 2
    }
  ]
}

Processus de Résolution

flowchart LR
    Scan["1️⃣ SCANNER<br/>Trouver paramètres<br/>avec variables"] 

    Identify["2️⃣ IDENTIFIER<br/>num_x: '$TIME_OFFSET'<br/>Contient variable"]

    Lookup["3️⃣ RECHERCHER<br/>Chercher dans dictionnaire<br/>pour $TIME_OFFSET"]

    Found["4️⃣ TROUVÉ<br/>Valeur:<br/>'125'"]

    Replace["5️⃣ REMPLACER<br/>num_x = <br/>'125'"]

    Ready["6️⃣ PRÊT<br/>Paramètre résolu<br/>Prêt pour casting"]

    Scan --> Identify
    Identify --> Lookup
    Lookup --> Found
    Found --> Replace
    Replace --> Ready

    style Scan fill:#fff9c4
    style Identify fill:#fff9c4
    style Lookup fill:#fff9c4
    style Found fill:#c8e6c9
    style Replace fill:#fff9c4
    style Ready fill:#c8e6c9

Avant Résolution :

{
  "num_x": "$TIME_OFFSET",
  "num_y": "200",
  "compare_type": 2
}
Note : num_x contient une référence de variable

Après Résolution :

{
  "num_x": "125",
  "num_y": "200",
  "compare_type": 2
}
Note : num_x contient maintenant la valeur résolue (toujours String, le casting vient ensuite) "text_y": "unreachable", "compare_type": 2 }
---

## Étape 4 : Casting de Type

Après résolution, les valeurs sont **converties au type attendu du paramètre**.

### Types de Casting

| De | À | Exemple | Processus |
|-----|-----|---------|----------|
| String | String | `"Network is unreachable"` | Pas de conversion |
| String | Double | `"25.5"` | Parser en float: `25.5` |
| String | JSON | `'{"status": "ok"}'` | Parser en objet: `{status: "ok"}` |
| String | Boolean | `"true"` | Parser en booléen: `true` |

### Exemple de Casting

```json
{
  "CompareNumber": [
    {
      "id": "3",
      "num_x": "$TEMPERATURE",
      "num_y": "50.0",
      "compare_type": 1
    }
  ]
}

flowchart TD
    Before["AVANT CASTING<br/>num_x = TEMPERATURE<br/>(String du dictionnaire)"]

    Resolved["APRES RESOLUTION<br/>num_x = 38.5<br/>(Toujours type String)"]

    CheckType["VERIFIER TYPE<br/>num_x s attend a: Double<br/>Type actuel: String"]

    Convert["CONVERTIR<br/>String 38.5<br/>vers Double 38.5<br/>(type cast)"]

    CastSuccess["CASTING REUSSI<br/>num_x = 38.5<br/>(Type Double)<br/>Pret pour execution"]

    CastError["ERREUR CASTING<br/>Impossible convertir abc<br/>en Double<br/>Execution s arrete"]

    Before --> Resolved
    Resolved --> CheckType
    CheckType --> Convert
    Convert --> CastSuccess
    CheckType -->|Valeur invalide| CastError

    style Before fill:#ffe0e0
    style Resolved fill:#fff9c4
    style CheckType fill:#fff9c4
    style Convert fill:#fff9c4
    style CastSuccess fill:#c8e6c9
    style CastError fill:#ffcdd2

Exemple Complet d'Exécution de Workflow

JSON du Workflow

{
  "Start": [
    {
      "id": "0",
      "variables": [
        {"variableName": "$PING_ERROR", "variableValue": ""},
        {"variableName": "$TEMPERATURE", "variableValue": "0.0"}
      ]
    }
  ],

  "CmdStage": [
    {
      "id": "1",
      "cmd_text": "ping -c 1 8.8.8.8",
      "cmd_error_output": "$PING_ERROR"
    }
  ],

  "CompareText": [
    {
      "id": "2",
      "text_x": "$PING_ERROR",
      "text_y": "unreachable",
      "compare_type": 2
    }
  ],

  "TextReport": [
    {
      "id": "3",
      "texte": "Réseau inaccessible: $PING_ERROR"
    },
    {
      "id": "4",
      "texte": "Réseau OK"
    }
  ],

  "End": [{"id": "100"}],

  "Links": [
    {"from": "0", "to": "1"},
    {"from": "1", "to": "2"},
    {"from": "2", "true": "3", "false": "4"},
    {"from": "3", "to": "100"},
    {"from": "4", "to": "100"}
  ]
}

Tableau d'Exécution

Étape Tâche Opération État Dictionnaire Notes
1 START (id:0) Initialiser variables {"$PING_ERROR": "", "$TEMPERATURE": "0.0"} Valeurs vides
2 CmdStage (id:1) Exécuter ping Identique Commande lancée...
3 CmdStage (id:1) Commande échoue Identique Erreur se produit
4 Runtime Resolver Enregistrer output {"$PING_ERROR": "Network is unreachable", "$TEMPERATURE": "0.0"} $PING_ERROR mise à jour
5 CompareText (id:2) Attendre exécution Identique Tâche prête
6 Runtime Resolver Résoudre paramètres Identique Scanne: text_x: "$PING_ERROR"
7 Runtime Resolver Remplacer variable Identique text_x = "Network is unreachable"
8 Runtime Resolver Caster types Identique text_x: String → String (pas changement)
9 CompareText (id:2) Exécuter comparaison Identique Compare contient "unreachable"
10 CompareText (id:2) Résultat: VRAI Identique Condition confirmée
11 Runtime Resolver Brancher vers Tâche 3 Identique Suivre lien "true"
12 TextReport (id:3) Attendre exécution Identique Tâche prête
13 Runtime Resolver Résoudre texte Identique Résoudre $PING_ERROR dans texte
14 TextReport (id:3) Exécuter avec texte résolu Identique Afficher message résolu
15 END (id:100) Workflow terminé Identique État final atteint

Timeline Visuelle d'Exécution

Exemple Concret : Vérifier le RTT NTP (Round Trip Time) avant d'accepter l'offset. Si RTT > 100ms, réessayer la synchronisation.

sequenceDiagram
    autonumber
    participant Start as 🏁 START
    participant Dict as 📦 Dictionnaire
    participant NTP1 as ⚙️ NtpSync 1
    participant Resolver as 🔍 Resolver
    participant CmpNum2 as 🔢 Compare 2
    participant NTP3 as 🔄 NtpSync 3
    participant CmpNum4 as 🔢 Compare 4
    participant Report as 📄 Report 5
    participant EndNode as 🎯 END

    rect rgb(230, 240, 255)
    Note over Start,Dict: 📋 PHASE 1 - INITIALISATION
    Start->>Dict: Initialiser Variables
    Note over Dict: Dictionnaire Créé
    Note over Dict: {$NTP_RTT: 0, $TIME_OFFSET: 0}
    end

    rect rgb(245, 230, 255)
    Note over Dict,NTP1: ⚙️ PHASE 2 - PREMIERE SYNC NTP
    Dict->>NTP1: Exécuter Tâche 1
    NTP1->>NTP1: Interroger time.google.com
    Note over NTP1: Réponse RTT: 300ms, Offset: 125ms
    NTP1->>Resolver: Output RTT=300, Offset=125
    Resolver->>Dict: Enregistrer Outputs
    Note over Dict: Dictionnaire Mis à Jour
    Note over Dict: {$NTP_RTT: 300, $TIME_OFFSET: 125}
    end

    rect rgb(255, 250, 230)
    Note over Dict,CmpNum2: 🔍 PHASE 3 - VERIFIER QUALITE RTT
    Dict->>CmpNum2: Exécuter Tâche 2
    CmpNum2->>Resolver: Résoudre param $NTP_RTT
    Resolver->>Dict: Chercher $NTP_RTT
    Dict-->>Resolver: Retourner 300
    Resolver->>CmpNum2: num_x = 300 (cast en Integer)
    CmpNum2->>CmpNum2: Comparer 300 < 100
    Note over CmpNum2: Résultat FALSE - RTT trop élevé!
    CmpNum2->>Dict: Brancher vers chemin FALSE
    end

    rect rgb(230, 255, 245)
    Note over Dict,NTP3: 🔄 PHASE 4 - REESSAYER SYNC NTP
    Dict->>NTP3: Exécuter Tâche 3 (Retry)
    NTP3->>NTP3: Interroger pool.ntp.org
    Note over NTP3: Réponse RTT: 45ms, Offset: 98ms
    NTP3->>Resolver: Output RTT=45, Offset=98
    Resolver->>Dict: Mettre à Jour Dictionnaire
    Note over Dict: Dictionnaire Mis à Jour
    Note over Dict: {$NTP_RTT: 45, $TIME_OFFSET: 98}
    end

    rect rgb(255, 250, 230)
    Note over Dict,CmpNum4: 🔍 PHASE 5 - REVERIFIER RTT
    Dict->>CmpNum4: Exécuter Tâche 4
    CmpNum4->>Resolver: Résoudre param $NTP_RTT
    Resolver->>Dict: Chercher $NTP_RTT
    Dict-->>Resolver: Retourner 45
    Resolver->>CmpNum4: num_x = 45 (cast en Integer)
    CmpNum4->>CmpNum4: Comparer 45 < 100
    Note over CmpNum4: Résultat TRUE - RTT acceptable!
    CmpNum4->>Dict: Brancher vers chemin TRUE
    end

    rect rgb(240, 255, 240)
    Note over Dict,Report: 📄 PHASE 6 - RAPPORT SUCCES
    Dict->>Report: Exécuter Tâche 5
    Report->>Resolver: Résoudre $NTP_RTT et $TIME_OFFSET
    Resolver->>Dict: Chercher les deux variables
    Dict-->>Resolver: $NTP_RTT=45, $TIME_OFFSET=98
    Resolver->>Report: Multi-variable résolu
    Report->>Report: Afficher message
    Note over Report: Sync NTP OK! RTT: 45 ms, Offset: 98 ms
    end

    rect rgb(230, 255, 230)
    Note over Report,EndNode: 🎯 PHASE 7 - COMPLETION
    Report->>EndNode: Workflow Terminé
    Note over Dict: État Final
    Note over Dict: {$NTP_RTT: 45, $TIME_OFFSET: 98}
    end

Résolution Multi-Variables

Un paramètre peut contenir plusieurs variables qui ont toutes besoin de résolution :

{
  "TextReport": [
    {
      "id": "5",
      "texte": "Offset NTP: $TIME_OFFSET ms | Localisation: Latitude $LATITUDE"
    }
  ]
}

Étapes de Résolution

flowchart LR
    Text["Paramètre texte:<br/>'Offset NTP: $TIME_OFFSET ms<br/>Localisation: Latitude $LATITUDE'"]

    Find["TROUVER variables:<br/>$TIME_OFFSET<br/>$LATITUDE"]

    Lookup1["CHERCHER $TIME_OFFSET:<br/>Trouvé: '125'"]

    Lookup2["CHERCHER $LATITUDE:<br/>Trouvé: '48.8566'"]

    Replace["REMPLACER les deux:<br/>'Offset NTP: 125 ms<br/>Localisation: Latitude 48.8566'"]

    Ready["PRÊT pour exécution"]

    Text --> Find
    Find --> Lookup1
    Find --> Lookup2
    Lookup1 --> Replace
    Lookup2 --> Replace
    Replace --> Ready

    style Text fill:#ffe0e0
    style Find fill:#fff9c4
    style Lookup1 fill:#fff9c4
    style Lookup2 fill:#fff9c4
    style Replace fill:#c8e6c9
    style Ready fill:#c8e6c9
Text["Parametre texte:
Erreur: PING_ERROR
Temp: TEMPERATURE"]

Find["TROUVER variables:<br/>PING_ERROR<br/>TEMPERATURE"]

Lookup1["RECHERCHER PING_ERROR:<br/>Trouve: Network unreachable"]

Lookup2["RECHERCHER TEMPERATURE:<br/>Trouve: 38.5"]

Replace["REMPLACER les deux:<br/>Erreur: Network unreachable<br/>Temp: 38.5"]

Ready["PRET pour execution"]

Text --> Find
Find --> Lookup1
Find --> Lookup2
Lookup1 --> Replace
Lookup2 --> Replace
Replace --> Ready

style Text fill:#ffe0e0
style Find fill:#fff9c4
style Lookup1 fill:#fff9c4
style Lookup2 fill:#fff9c4
style Replace fill:#c8e6c9
style Ready fill:#c8e6c9

```


Scénarios d'Erreur

Scénario 1 : Variable Non Déclarée

json { "CompareText": [ { "id": "2", "text_x": "$UNDEFINED_VAR", "text_y": "test" } ] }

flowchart TD
    Scan["SCANNER parametre<br/>Trouver: UNDEFINED_VAR"]

    Lookup["RECHERCHER en dictionnaire<br/>Chercher: UNDEFINED_VAR"]

    NotFound["NON TROUVEE<br/>Variable n existe pas"]

    Error["ERREUR<br/>Variable UNDEFINED_VAR<br/>non trouvee en<br/>dictionnaire runtime"]

    Stop["ARRETER EXECUTION<br/>Workflow echoue"]

    Scan --> Lookup
    Lookup --> NotFound
    NotFound --> Error
    Error --> Stop

    style Scan fill:#fff9c4
    style Lookup fill:#fff9c4
    style NotFound fill:#ffcdd2
    style Error fill:#ffcdd2
    style Stop fill:#ffcdd2

Scénario 2 : Erreur de Casting

{
  "CompareNumber": [
    {
      "id": "2",
      "num_x": "$TEXT_VALUE",
      "num_y": "50.0"
    }
  ]
}

Dictionnaire: {"$TEXT_VALUE": "abc"} (pas un nombre valide)

flowchart TD
    Resolve["RESOUDRE<br/>num_x = abc"]

    CheckType["VERIFIER TYPE<br/>num_x s attend: Double<br/>Actuel: String"]

    TryConvert["ESSAYER CONVERTIR<br/>abc vers Double"]

    ConvertFail["CONVERSION ECHOUE<br/>abc n est pas<br/>un nombre valide"]

    Error["ERREUR<br/>Impossible caster abc<br/>en Double"]

    Stop["ARRETER EXECUTION"]

    Resolve --> CheckType
    CheckType --> TryConvert
    TryConvert --> ConvertFail
    ConvertFail --> Error
    Error --> Stop

    style Resolve fill:#ffe0e0
    style CheckType fill:#fff9c4
    style TryConvert fill:#fff9c4
    style ConvertFail fill:#ffcdd2
    style Error fill:#ffcdd2
    style Stop fill:#ffcdd2

Machine d'État du Dictionnaire Runtime

Le dictionnaire runtime évolue au cours du cycle de vie du workflow :

flowchart TD
    Start["START NODE<br/>Dictionary Initialization<br/>Variables declared<br/>Initial values set"] 

    Task1Ready["Task 1 Ready<br/>Waiting for execution"]

    Task1Exec["Task 1 Execution<br/>Processing command<br/>Generating output"]

    Task1Register["Register Output<br/>Runtime Resolver saves<br/>Output to Dictionary<br/>VAR1 = value1"]

    Task1Done["Task 1 Complete<br/>Dictionary Updated<br/>New state stored"]

    Task2Ready["Task 2 Ready<br/>Waiting for execution<br/>Has parameters"]

    Task2Scan["Scan Parameters<br/>Runtime Resolver finds<br/>Variable references"]

    Task2Resolve["Resolve Variables<br/>Replace variables<br/>With dictionary values"]

    Task2Cast["Cast Types<br/>Convert to expected<br/>Parameter types"]

    Task2Exec["Task 2 Execution<br/>Using resolved values<br/>Parameters ready"]

    Task2Done["Task 2 Complete<br/>Output registered<br/>Dictionary extends"]

    End["WORKFLOW END<br/>Final dictionary state<br/>All variables persisted"]

    Start --> Task1Ready
    Task1Ready --> Task1Exec
    Task1Exec --> Task1Register
    Task1Register --> Task1Done
    Task1Done --> Task2Ready
    Task2Ready --> Task2Scan
    Task2Scan --> Task2Resolve
    Task2Resolve --> Task2Cast
    Task2Cast --> Task2Exec
    Task2Exec --> Task2Done
    Task2Done --> End

    style Start fill:#c8e6c9
    style Task1Ready fill:#e3f2fd
    style Task1Exec fill:#f3e5f5
    style Task1Register fill:#fff9c4
    style Task1Done fill:#c8e6c9
    style Task2Ready fill:#e3f2fd
    style Task2Scan fill:#fff9c4
    style Task2Resolve fill:#fff9c4
    style Task2Cast fill:#fff9c4
    style Task2Exec fill:#f3e5f5
    style Task2Done fill:#c8e6c9
    style End fill:#c8e6c9

Bonnes Pratiques pour la Résolution Runtime

1. Déclarer les Variables Tôt

Toujours déclarer toutes les variables au nœud START :

 Bon : Toutes variables déclarées au départ
{
  "Start": [{"id": "0", "variables": [...]}]
}

 Mauvais : Déclarations manquantes
{
  "CmdStage": [{"id": "1", "cmd_error_output": "$UNDEFINED"}]
}

2. Utiliser des Noms de Variables Descriptifs

 Bon : But clair
"cmd_error_output": "$PING_ERROR"
"cmd_result_output": "$NETWORK_STATUS"

 Mauvais : Noms nériques
"cmd_error_output": "$x"
"cmd_result_output": "$var1"

3. Initialiser avec les Types Corrects

 Bon : Valeurs par faut appropriées au type
{"variableName": "$ERROR_MSG", "variableValue": ""}
{"variableName": "$TEMPERATURE", "variableValue": "0.0"}
{"variableName": "$DATA", "variableValue": "{}"}

 Mauvais : Types mal appariés
{"variableName": "$TEMPERATURE", "variableValue": "zéro"}

4. Vérifier la Compatibilité des Types

Assurer que les types de paramètres correspondent aux castages attendus :

 Bon : Types compatibles
"num_x": "$TEMPERATURE"  // String stocké, cast en Double
"texte": "$ERROR_MSG"    // String reste String

 Mauvais : Incompatibilité de type
"num_x": "$TEXT_VALUE"   // Contient "abc", impossible caster en Double