Bonjour, je suis en train de mettre en place un systeme de file d'attente à l'aide des packages dbms_aqadm et dbms_aq.
J'ai donc créé une queue_table, avec une seule queue à l'interieur. Des utilisateurs peuvent envoyer des messages, ils sont alors placés dans une file d'attente, puis un autre utilisateur les recupere un à un. Jusque la, tout va bien.
Ma queue_table est bien mise à jour lors de l'envoi d'un message (on vois la date de l'envois, qui l'a envoyé, combien de temps le message reste dans la file d'attente, etc.), mais par contre elle n'est pas mise à jour lors de la reception d'un message (date de reception, nom du receptionneur ...).
De plus, les messages ne sont pas considérés comme lus, leur statut reste inchangé, et ils passent dans la table d'exception une fois que le temps arrive à expiration.
Pourtant, je les vois à la reception, ils sont tous receptionnés sans probleme, sans doublons, tout marche nickel.
J'arrive pas à comprendre d'où vient le problème, je me doute que ca vient des procédures de dequeue/enqueue mais à part ca...
Voici en gros les procédures que j'utilise:
Enqueue:
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
CREATE OR REPLACE procedure enqueue_pharm(usermsg commande, urgence number) authid definer IS
enq_msgid raw(16);
eot dbms_aq.enqueue_options_t;
mpt dbms_aq.message_properties_t;
envoyeur sys.aq$_agent;
pragma autonomous_transaction;
begin
envoyeur := sys.aq$_agent(user, NULL, 0);
mpt.priority := urgence;
mpt.sender_id := envoyeur;
IF urgence < 5 then
eot.sequence_deviation := dbms_aq.top; -- si le chiffre de l'urgence est < 5
else -- alors on le met au dessus de tous les
eot.sequence_deviation := NULL; -- messages sinon, on le met a la suite
end IF; -- comme les autres
IF urgence < 10 then -- si l'urgence est < 10 on le place dans
mpt.expiration := 60*5; -- l'exception au bout de 5 min
else
mpt.expiration := 1800; -- sinon c'est au bout de 30 min
end IF;
dbms_aq.enqueue('aqadmin.commande_attente', eot, mpt, usermsg, enq_msgid);
commit;
end enqueue_pharm; |
Dequeue:
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
CREATE OR REPLACE procedure dequeue_pharm(username_d varchar2) authid definer IS
deq_msgid raw(16);
dot dbms_aq.dequeue_options_t;
mpt dbms_aq.message_properties_t;
payload_d commande;
tmp pls_integer;
pas_dispo exception;
pragma autonomous_transaction;
begin
dot.consumer_name := username_d;
dot.navigation := dbms_aq.first_message;
dot.visibility := dbms_aq.immediate;
dbms_aq.dequeue('aqadmin.commande_attente', dot, mpt, payload_d, deq_msgid);
SELECT quantite_i
INTO tmp
FROM inventaire
WHERE nom_i = payload_d.nom_c;
IF (tmp - payload_d.quantite_c) > 0 then
UPDATE inventaire
SET quantite_i = quantite_i - payload_d.quantite_c
WHERE nom_i = payload_d.nom_c;
else
raise pas_dispo;
end IF;
INSERT INTO sortie_prep (nom_s, quantite_s, dequeue_par, date_de_dequeue)
VALUES (payload_d.nom_c, payload_d.quantite_c, username_d, systimestamp);
commit;
exception
when pas_dispo then
dbms_output.put_line('il n y a pas ce qu il faut pour satisfaire la commande');
commit;
end dequeue_pharm; |
Et j'utilise deux autres petites procédures pour simplifier les choses:
Code :
1 2 3 4 5 6 7 8
|
CREATE OR REPLACE procedure mise_en_attente (quantite_m number, nom_m varchar2, priorite_m number) IS
usermsg aqadmin.commande;
begin
usermsg := aqadmin.commande(nom_m,quantite_m);
enqueue_pharm(usermsg, priorite_m);
end mise_en_attente; |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| CREATE OR REPLACE procedure recuperer_messages authid definer IS
qlist dbms_aq.aq$_agent_list_t;
agent_msg sys.aq$_agent;
listen_timeout exception;
pragma exception_init(listen_timeout, -25254);
begin
qlist(0) := sys.aq$_agent(user, 'aqadmin.commande_attente', NULL);
-- loop
begin
dbms_aq.listen(agent_list => qlist, wait => 5, agent => agent_msg);
IF agent_msg.name = user then
dequeue_pharm(user);
end IF;
commit;
end;
--end loop;
exception
when listen_timeout then
dbms_output.put_line('tous les messages de la file d attente ont été lus');
end recuperer_messages; |
J'espere que c'est comprehensible, si vous avez besoin de précisions n'hesitez pas!
Merci d'avance, Crustyz