Aller au contenu principal

Exécuter une fonction

Objectif​

Faire qu’une chose se produise sans que personne n’enregistre un enregistrement : un rappel envoyé chaque nuit, un lot d’enregistrements rangé chaque heure, un long travail lancé à la main et laissé se terminer. Et pouvoir lire ensuite exactement ce que chaque exécution a fait.

Pourquoi cela existe​

Tout ce que font les autres scripts d’une solution commence par l’enregistrement de quelqu’un : une étape de plug-in s’exécute dans une écriture, une API personnalisée quand un autre système l’appelle. Mais certains travaux n’appartiennent à aucune écriture : ils dépendent d’une heure, ou d’un lot trop grand pour que quelqu’un l’attende.

Une fonction est un script BS Lang que le service des fonctions exécute de lui-même, dans son propre processus et aussi longtemps que vous l’autorisez. C’est un composant de votre solution, comme un formulaire ou un script : écrit en Dev, il voyage vers Test et Production dans le package de la solution.

Avant de commencer​

  • Une solution, avec un éditeur.
  • Les tables que votre fonction lira et écrira.
  • Si elle appelle un service externe ou envoie des e-mails, la variable d’environnement qui le nomme — voir Appeler un service externe depuis un script.

Étapes​

  1. Ouvrez votre solution, sélectionnez Fonctions dans la barre latérale, puis Nouveau.
  2. Dans l’onglet Script, écrivez ce que fait la fonction. Elle peut lire et écrire des enregistrements et des fichiers, appeler des services externes et importer vos scripts de solution avec import — comme une étape de plug-in. L’œil au bout de la barre d’onglets liste tout ce que vous pouvez appeler.
  3. Dans l’onglet Paramètres, donnez-lui un nom d’affichage. Le nom logique se remplit tout seul.
  4. Décidez quand elle s’exécute. Toute fonction peut s’exécuter à la main. Pour qu’elle s’exécute aussi d’elle-même, cochez S’exécute selon une planification et choisissez un intervalle : toutes les 15 minutes, toutes les 6 heures, tous les jours. Pour une planification quotidienne, vous pouvez fixer une heure et son fuseau horaire.
  5. Fixez la durée maximale : combien de temps une exécution peut durer avant d’être arrêtée. 15 minutes par défaut, un jour au plus.
  6. Sélectionnez Enregistrer. Un script qui ne s’analyse pas est refusé tout de suite, avec la ligne fautive.
  7. Sélectionnez Exécuter maintenant. L’onglet Exécutions s’ouvre et suit l’exécution : En file d’attente, En cours, puis comment elle s’est terminée. Sélectionnez l’exécution pour lire son journal.

Écrire un journal​

Personne ne regarde pendant qu’une fonction s’exécute : son journal est le moyen de savoir ce qu’elle a fait.

var due = queryRecords('par_membership', 'par_reminder_state', 'due');
log('Reminders due: ' + toJson(due.length()));

for (var i: int = 0; i < due.length(); i++) {
updateRecord('par_membership', due[i].id, { par_reminder_state: 'sent' });
log(due[i]);
}
  • Le texte est écrit tel quel, un nombre comme vous l’écririez, et un enregistrement ou une liste en JSON — log(due[i]) montre donc l’enregistrement entier tel que l’exécution l’a vu.
  • L’onglet Exécutions affiche les lignes pendant que l’exécution est encore en cours, avec quelques secondes de retard.
  • Une exécution conserve au plus 5 000 lignes ; la dernière conservée indique que le journal est plein.
  • Conserver les lignes de journal, dans l’onglet Paramètres, coupe la journalisation. log fonctionne toujours et ne conserve rien : vous n’avez jamais à modifier le script pour le faire taire ni pour le réactiver.

Terminer une exécution exprès​

stop('reason') termine l’exécution à cet endroit, comme une réussite qui dit pourquoi :

if (due.length() == 0) {
stop('Nobody is due a reminder tonight.');
}

Le résultat de l’exécution affiche cette phrase. Ce n’est pas un échec, et la liste ne l’affiche pas ainsi.

Démarrer une fonction depuis un script​

Une fonction n’a pas besoin d’horloge. Une Custom API, une étape de plugin ou une autre fonction peut la démarrer avec startFunction, lui passer une entrée et récupérer l’identifiant de l’exécution aussitôt — le travail se fait ensuite, dans le service Functions. C’est ainsi qu’une demande qui nécessite une heure de travail reçoit une réponse en un instant.

// A Custom API: POST reports { "period": "2026-10" }
var run = startFunction('par_sales_report', { period: getInput('period') });
setStatus(202);
setOutput('run', run);
// The function
var asked = functionInput();
// … the long work …
setResult({ period: asked.period, total: total });
// A second Custom API: GET reports/runs/{run}
var run = functionRun(getInput('run'));
if (run == null) { setStatus(404); } else { setOutput('status', run.status); setOutput('report', run.result); }
  • startFunction(name, input) renvoie l’identifiant de l’exécution. L’entrée — un enregistrement, une liste, une valeur ou null — est ce que la fonction lit avec functionInput(). Une exécution lancée par sa planification ou par Run now n’a pas d’entrée et lit null.
  • setResult(value) est ce que l’exécution renvoie. Seule la dernière valeur est conservée, et seulement si l’exécution réussit. Gardez-la petite — un résumé, ou la clé d’un fichier —, car elle est lue chaque fois que quelqu’un demande où en est l’exécution.
  • functionRun(id) renvoie { id, function, status, outcome, result, queuedAt, startedAt, finishedAt }, ou null s’il n’existe pas d’exécution de ce nom.
  • Depuis une étape de plugin, l’exécution est démarrée à l’intérieur de l’écriture : si l’écriture est refusée, l’exécution ne démarre jamais.
  • Les exécutions démarrées par un script ne sont pas limitées à une à la fois. Deux personnes qui demandent en même temps obtiennent deux exécutions. La règle d’une à la fois vaut pour la planification et Run now.
  • Dans l’onglet Runs, une telle exécution indique Comment elle a démarré : Un script, et la sélectionner affiche son Entrée et son Résultat au-dessus du journal.
  • Si la fonction n’existe pas ou est désactivée, startFunction arrête le script avec la raison : l’appelant ne s’entend jamais dire qu’un travail a commencé alors qu’il n’a pas commencé.

Être prévenu à la fin​

Un appelant qui préfère ne pas redemander sans cesse peut être prévenu. startFunctionWithCallback est startFunction avec un argument de plus : le nom d'une variable d'environnement qui contient l'adresse à prévenir. Quand l'exécution se termine — quelle qu'en soit la façon —, son résultat y est envoyé une fois.

// A Custom API: POST totals
var run = startFunctionWithCallback('par_invoice_totals', null, 'par_totals_done');
setStatus(202);
setOutput('run', run);

Ce qui arrive :

{ "run": "…", "function": "par_invoice_totals", "status": "Succeeded",
"outcome": null, "result": { "invoices": 3, "total": 165.5 }, "finishedAt": "…" }
  • Jamais d'URL dans le script. Le troisième argument nomme une variable d'environnement, comme pour callService ; un administrateur décide vers où elle pointe, environnement par environnement. Un nom que la solution ne déclare pas arrête le script avant que rien ne démarre.
  • Envoyé une fois, sans nouvelle tentative. Dans l'onglet Exécutions, l'exécution sélectionnée affiche son Rappel et ce qu'il est devenu — Delivered (HTTP 200), le statut renvoyé par le service, ou la raison pour laquelle il n'a pas pu être appelé. Un appelant qui l'a manqué peut toujours lire l'exécution avec functionRun.
  • Le statut de l'exécution n'en dépend pas. Une exécution qui a fait son travail réussit même si le service à prévenir est indisponible.

Écrire un fichier​

Une fonction peut écrire dans le stockage d'objets avec les mêmes appels qu'une Custom API — putFile, putFileAs, getFile, listFiles et deleteFile —, même si personne n'est connecté pendant son exécution.

var key = 'orders/' + today() + '.csv';
putFileAs('par-order-exports', key, csv, 'text/csv');
setResult({ bucket: 'par-order-exports', key: key, rows: orders.length() });
  • Le fichier va dans le stockage de votre organisation et compte dans son quota de stockage. Une écriture qui dépasserait le quota fait échouer l'exécution.
  • Dans Administration → Stockage, le fichier apparaît comme envoyé par function:<name> : c'est la fonction qui l'a écrit, pas la personne qui a cliqué sur Exécuter maintenant.
  • C'est ainsi qu'une fonction renvoie plus qu'un résumé : écrivez les données dans un fichier et mettez sa clé dans le résultat.
  • Rien ne supprime les anciens fichiers à votre place. Une fonction qui en écrit un chaque nuit doit supprimer ceux dont elle n'a plus besoin, comme le fait l'exemple functions-nightly-export-to-storage.

Comment une exécution se termine​

StatutCe qui s’est passé
RéussieLe script est allé au bout, ou s’est arrêté avec stop(...)
ÉchouéeLe script a levé une erreur, une écriture a été refusée, la durée maximale a été dépassée ou le service s’est arrêté pendant l’exécution. Le résultat dit lequel
AnnuléeQuelqu’un a cliqué sur Annuler l’exécution

Une exécution échouée n’est jamais relancée à votre place. Une fonction peut durer longtemps, et refaire vingt-neuf minutes de travail à votre insu serait pire que s’arrêter. Lisez pourquoi elle a échoué, corrigez ce qu’il faut et cliquez sur Exécuter maintenant.

Vérifier que cela a fonctionné​

  • L’exécution est Réussie et son journal dit ce que vous attendiez.
  • Ouvrez un enregistrement modifié par la fonction et regardez son historique d’audit : la modification est attribuée à la fonction, pas à une personne. Une fonction s’exécute en tant que plateforme, sans personne derrière.
  • Pour une fonction planifiée, Prochaine exécution dans l’onglet Paramètres est le prochain moment où elle s’exécutera d’elle-même.

À savoir​

  • Une exécution à la fois. Tant qu’une exécution attend ou tourne, « Exécuter maintenant » est refusé et une planification qui arrive à échéance est sautée jusqu’à la suivante. Un passage nocturne trop long ne démarre jamais deux fois sur les mêmes enregistrements.
  • « Exécuter maintenant » exécute ce qui est enregistré et n’est pas proposé tant qu’il reste des modifications non enregistrées.
  • Désactivée veut dire désactivée. Une fonction désactivée ne s’exécute ni selon sa planification ni à la main.
  • Modifier le script ne déplace pas la planification ; modifier la planification, si.
  • Annuler l’exécution arrête un script en quelques secondes — même une boucle qui ne touche aucun enregistrement.
  • Chaque fonction conserve ses 200 exécutions les plus récentes.

Dépannage​

SymptômeCause probableSolution
Exécuter maintenant est griséModifications non enregistrées, ou fonction désactivéeEnregistrez ; activez-la
Cette fonction est déjà en cours d’exécutionUne exécution attend ou tourneAttendez, ou sélectionnez-la et Annuler l’exécution
Échouée : Stopped after … minutesDurée maximale dépasséeAugmentez la durée maximale, ou faites faire moins à chaque exécution
Échouée car le service s’est arrêté pendant l’exécutionLe service a redémarréRelancez-la
Le journal est videConserver les lignes de journal est désactivé, ou le script n’appelle jamais logActivez-le ; ajoutez log(...)
L'exécution a échoué : There is not enough storage leftLe quota de stockage de l'organisation est épuiséSupprimez les fichiers inutiles ou passez à une offre supérieure
L'exécution a échoué : Object storage is not configured for the Functions serviceLe déploiement n'a pas fourni de paramètres de stockage au service FunctionsAdressez-vous à votre administrateur

Voir aussi​