Exemple File d'attente avec un automate

De Wiki1000
Version du 11 avril 2013 à 09:03 par Syfre (discuter | contributions)
(diff) ← Version précédente | Voir la version courante (diff) | Version suivante → (diff)

Sommaire

Dans cet exemple nous allons mettre en oeuvre le design pattern file d'attente en utilisant :

  • Une file d'attente stockée dans la base de données
  • Un automate pour consommer les messages de cette file d'attente (consommateur)
  • Un code script pour générer les messages (producteur)
  • Un processus de traitement pour traiter les messages

Configuration de la file d'attente

La file d'attente est configurée par un objet TdbmMessageQueue du référentiel:

image1.png

  • Le nom de paramétrage de la file est DBQUEUE
  • Le type de la file est DatabaseMQ ce qui indique qu'il s'agit d'une file gérée en base de données
  • L'attribut QueueConnextionInfos indique le nom de la classe dans laquelle seront stockés les messages, il s'agit de la classe générique permettant de stocker n'importe quel message.

Code snippet du producteur

Le code générant un message dans la file est le suivant :

//Procedure TestQueueMessage;
var msg:TdbmQueueMessage; idx:Integer;
begin
  for idx:=1 to 1 do
   begin
     msg := TdbmQueueMessage.Create;
     msg.QueueName := 'DBQUEUE';
     msg.AddParameter('uneChaine','some text');
     msg.AddParameter('unEntier',1999);
     msg.BinaryContent.LoadFromFile('c:\image.jpg');
     msg.Post;
   end;
end;

Il peut être directement exécuté à partir du concepteur de modèle.

Notez que :

  • Ce code ne connait pas la configuration de la file, il peut fonctionner avec n'importe quel type de file.
  • Il ne fait pas référence à TdbmStoredQueueMessage (ce qui serait propre à la configuration de la file) mais à TdbmQueueMessage qui est un type non persistant générique représentant un message.
  • Il écrit le message en base par un Post sur le message, c'est une action générique indépendante du type de la file.
  • Le message contient deux paramètres et un contenu binaire
  • Il ni a pas besoin de déclarer une transaction.

Code snippet du processus de traitement

La classe traitant les messages est la suivante :

unit TestSYFREWF;
interface
 
Type
  MyProcessus = Class(TitObject)
  public
    uneChaine: string;
    unEntier: integer;
    Procedure Execute;
  end;
 
Implementation
 
{MyProcessus}
 
Procedure MyProcessus.Execute;
//Procedure Execute;
var aMsg:TdbmQueueMessage; idx:Integer;
begin
  if Assigned(UserContext.TaskContext) then
   begin
     UserContext.TaskContext.AddMessage('MyProcessus.Execute');
     if Assigned(UserContext.TaskContext.EventContext.receivedMsg) then
       begin
         aMsg := UserContext.TaskContext.EventContext.receivedMsg;
         UserContext.TaskContext.AddMessage('Has a message');
         for idx:=0 to aMsg.Count-1 do
          begin
            UserContext.TaskContext.AddMessage(aMsg.DisplayStrings[idx]);
          end;
         // simulate job
         sleep(5000);
       end
       else UserContext.TaskContext.AddMessage('No message');
   end
   else showMessage('not in a task');
end;;
end.

Ce processus réalise :

  • Vérifie qu'il s'exécute bien dans le contexte du tâche
  • Trace dans les messages du contexte son exécution
  • Récupère le message consommé (aMsg)
  • Trace tous les paramètres du message dans messages du contexte
  • Simule l'exécution d'un traitement.

Le processus sera exécuté par la tâche d'automate consommant les messages.

Configuration de la tâche d'automate

Evènement :

image3.png

  • L'évènement référence la file d'attente par son nom de paramétrage (DBQUEUE)
  • L'intervalle de test est zéro (?)

Tâche :

image2.png

Cet automate est configuré ainsi :

  • L'évènement est de type File d'attente
  • La tâche est de type traitement
  • Les paramètres de la tâche référence le processus MyProcessus
  • L'état suivant est -1

Exécution

Exécution du code producteur :

image4.png

  • On constate que ce code a créé un objet dans la classe TdbmStoredQueueMessage.
  • Les paramètres du message sont stockés dans l'attribut Data
  • Le contenu binaire est stocké dans l'attribut BinaryContent

Démarrage de l'automate :

On utilise une console SNMTP pour superviser l'exécution :

image5.png

On constate que

  • l'évènement DBQUEUE est déclenché.
  • L'exécution de la tâche de traitement est réalisé.

La tâche de traitement génère une entrée dans le journal :

Tâche : Tâche de traitement Traiter un msg de DBQUEUE
Société : Test SYFRE Workflow
Utilisateur: syfre
Base(s) : TestWorkFlowdup_7
Mode Soc. : Enchainer sur ces sociétés
Société(s) : 
Début : 11/04/2013 09:39:19
Fin : 11/04/2013 09:39:24
Durée : 5 s
Fichiers : 0
Statut : 0 OK

MyProcessus.Execute
Has a message
MessageClassName="TStaticRegClass"
MessageDatetime="11/04/2013"
MessageUser="syfre"
MessageOID="000000000000000000E30001A0FF0008"
MessageID="166"
Topic="WSMQCOPY"
State="1"
OriginalUniqueID=""
idOTP="227"
ObjectClassLabel="Classe message stocké d'une file d'attente"
ObjectClassName="TDBMSTOREDQUEUEMESSAGE"
oid="000000000000000000E30001A0FF0008"
oiddbmQueue=""
oidShare=""
QueueName="WSMQCOPY"
queueTopic="WSMQCOPY"
ShareInfo=""
ShareInstanceInfo=""
ShareInstanceLevel="2"
ShareInstanceRequestedLevel="-1"
ShareLevel="0"
UniqueID="166"
UpdDate="11/04/2013"
UpdStamp="00017D6100000022"
UpdUser="syfre"
uneChaine="some text"
unEntier="1999"

Production de plusieurs messages

On peut modifier le code du producteur pour générer plusieurs messages :

//Procedure TestQueueMessage;
var msg:TdbmQueueMessage; idx:Integer;
begin
  for idx:=1 to 5 do
   begin
     msg := TdbmQueueMessage.Create;
     msg.QueueName := 'DBQUEUE';
     msg.AddParameter('uneChaine','some text');
     msg.AddParameter('unEntier',1999);
     msg.BinaryContent.LoadFromFile('c:\image.jpg');
     msg.Post;
   end;
end;

On constate les déclenchements de l'automate :

image6.png

Chaque déclenchement est espacé d'environ 5 secondes qui correspondes au temps de traitement du processus.

Utilisation de plusieurs consommateurs

Il est possible de démarrer plusieurs services sur le même automate pour mettre en oeuvre plusieurs consommateurs :

[\SOFTWARE\Sage\Ligne 1000\Administration\IPC\SYFRE1]
ipcMode=ipcTCP
tcpPort=8091
section=SYFRE

[\SOFTWARE\Sage\Ligne 1000\Administration\IPC\SYFRE2]
ipcMode=ipcTCP
tcpPort=8092
section=SYFRE

[\SOFTWARE\Sage\Ligne 1000\Administration\Servers\SYFRE]
Master Profil=dbMasterTahoe
Server Societies=Test SYFRE Workflow
Server Application=Test-SYFRE-WorkFlow
Server User=syfre
Server Password=
Public Folder=C:\Mes documents\Server\
IPC Started=0
BP Started=0
Automate Name=SYFRE
Automate Started=1
DEBUGGER Started=0
DEBUGGER Users=syfre,toto,titi
SESSIONS profil=CONFIG_SESSION_1
SOAP Profil=CONFIG_SOAP_1
SNMP Profil=CONFIG_SNMP_1
SMTP Profil=CONFIG_SMTP_1
PROCESS Profil=CONFIG_PROCESS_1
--HTTP Profil=CONFIG_HTTP_INTERNAL
Tip-20px.png Tip : Les services ne démarre pas de serveur HTTP

Une fois démarré chaque service exécute le même automate :

image7.png

Lorsque l'on crée plusieurs messages dans la file d'attente :

image8.png

On constate que les messages ont été consommés par les deux services.

Outils personnels