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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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