Je travaille sur une fonction PL/pgSQL "interpolate_values" avec des calculs qui prennent du temps. Une table appelée « interpolation_jobs » contient des informations de surveillance au sujet de chaque appel de fonction, de sorte que la progression d'un appel de fonction avec une job_id donnée doit être observable parMise à jour immédiate des fonctions PL/pgSQL
SELECT status FROM interpolation_jobs WHERE id = job_id;
La colonne « statut » contient l'une des valeurs « mis en attente » , "en cours d'exécution" ou "fait". Au début de la fonction, le statut passe de « mis en attente » à « courir », à la fin, il est réglé sur « fait »:
CREATE OR REPLACE FUNCTION interpolate_values (job_id INTEGER)
RETURNS VOID
LANGUAGE plpgsql VOLATILE
AS $$
DECLARE
BEGIN
EXECUTE 'UPDATE interpolation_jobs
SET status = ''running'', progress = 0.0
WHERE id = ' || job_id || ';';
--
-- ... some extensive database computations ...
--
EXECUTE 'UPDATE interpolation_jobs
SET status = ''done''
WHERE id = ' || job_id || ';';
END;
$$;
Mon problème est que le statut n'est pas mis à jour au cours de la fonction appel. Les mises à jour ont effectivement lieu lorsque l'appel de fonction retourne. Ainsi, le statut passe directement de «en attente» à «terminé». Les lignes
EXECUTE 'UPDATE interpolation_jobs
SET status = ''running'', progress = 0.0
WHERE id = ' || job_id || ';';
n'ont aucun effet.
Y a-t-il une possibilité de mettre à jour les valeurs immédiatement dans PL/pgSQL, de sorte que les nouvelles valeurs soient accessibles avant que l'appel de fonction ne retourne?
Merci!
EDIT:
Merci pour toutes vos réponses qui m'a beaucoup aidé à comprendre les problèmes généraux des opérations de base de données asynchrones. L'approche de dblink fonctionne pour moi. Il est nécessaire de spécifier IP/Port/utilisateur si la même base de données est utilisée:
SELECT * FROM current_database() INTO _db_name;
PERFORM dblink_connect('dbname=' || _db_name);
PERFORM dblink_exec('UPDATE interpolation_jobs SET status = ''running'' WHERE id =' || _job_id);
--
-- ... some extensive database computations ...
--
PERFORM dblink_exec('UPDATE interpolation_jobs SET status = ''done'' WHERE id =' || _job_id);
PERFORM dblink_disconnect();
En bref: non. Les mises à jour de la table d'état font partie de la transaction et ne peuvent être vues que par d'autres processus une fois la transaction validée. Vous auriez besoin d'une notification asynchrone pour accomplir ce que vous voulez. voir 'LISTEN' ou 'NOTIFY' dans le manuel. – wildplasser