Nous cherchons à faire en sorte qu'une certaine tâche de service ne soit jamais executée 2 fois en même temps sur l'intégralité des instance de process en cours.
Il nous faut donc un moyen pour faire attendre les autres instances que la tâche prise soit libérée.
Doit-on passer par les "event handlers" ? Par une modélisation avec un flag en BDM ? De quel côté chercher ?
Je n'ai jamais implémenté ce type de cas d'utilisation mais effectivement les deux options que vous proposez (utilisation des "event handlers" et flag stocké dans le BDM) me semble pertinentes.
J'aurais une préférence pour une solution basée sur un flag dans le BDM (avec tâche de service pour tester le flag et boucle avec un timer).
Une variante serait de ne pas stocker de flag mais d'interroger directement l'API du moteur pour savoir si une instance de tâche correspondant à la définition qui nous intéresse est en cours d'exécution.
En fonction des solutions proposées, quel est la part de risque que le test (qu'il soit fait sur un flag en BDM ou sur la présence de la tâche dans le moteur) soit exécuté au même moment par le moteur et passe sur 2 instances à la fois ?
Comment s'assurer que le test se fasse dans une seule transaction ?
Le besoin est le calcul d'une référence séquentielle basée sur les références existantes déjà présentes en BDM, il faut s'assurer que la référence soit unique. Le problème est qu'entre le temps ou on fait la requête en BDM (afin de passer le résultat en entrée de connecteur), et le temps que s'exécute le connecteur, nous avons eu parfois des tâches qui s'éxécutaient en même temps. Conséquence -> numérotation séquentielle plantée et tâches en échec.
Si le besoin est d'avoir un identifiant unique peut être qu'utiliser le persitenceId gérer par le BDM via la base de données peut répondre à votre cas d'utilisation ? Le persitenceId est un nombre entier (type Java long) qui est gérer par la base de données donc pas de risque de duplication. Sinon il est également possible d'ajouter une contrainte d'unicité sur un attribut d'un objet de son choix et de la même manière c'est la base de données qui va garantir l'unicité.
Non, nous n'avons pas la maitrise du persistenceId, cette référence n'étant pas calculée au début du process.
Nous devons avoir la maitrise du formalisme et du compteur de cette référence.
J'ai commencé à implémenter une porte exclusive qui renvoit vers un timer (avec random de durée entre 1 et 5 secondes) dans le cas ou le test suivant return true :
import org.bonitasoft.engine.api.ProcessAPI
import org.bonitasoft.engine.search.SearchOptionsBuilder
import org.bonitasoft.engine.search.SearchResult
import org.bonitasoft.engine.bpm.process.ProcessDeploymentInfo
import org.bonitasoft.engine.bpm.process.ProcessDeploymentInfoSearchDescriptor
import org.bonitasoft.engine.bpm.process.ProcessInstance
import com.bonitasoft.engine.bpm.process.impl.ProcessInstanceSearchDescriptor
import org.bonitasoft.engine.bpm.flownode.FlowNodeInstance
import org.bonitasoft.engine.bpm.flownode.FlowNodeInstanceSearchDescriptor
//RECHERCHE DES PROCESS DÉPLOYÉS (non supprimés, peu importe l'activation)
final SearchOptionsBuilder builderProcess = new SearchOptionsBuilder(0,10000)
builderProcess.filter(ProcessDeploymentInfoSearchDescriptor.NAME, "Contrat")
builderProcess.and()
builderProcess.filter(ProcessDeploymentInfoSearchDescriptor.CONFIGURATION_STATE, "RESOLVED")
final SearchResult<ProcessDeploymentInfo> processDeploymentInfoResult = apiAccessor.getProcessAPI().searchProcessDeploymentInfos(builderProcess.done())
//POUR CHAQUE PROCESS DEPLOYÉ---------------------------------------------
for (final ProcessDeploymentInfo process : processDeploymentInfoResult.getResult()){
//RECHERCHE DES CASES/INSTANCES DE PROCESS AVEC PROCESS_DEFINITION_ID = PROCESS TROUVÉ---------------------------------------------
final SearchOptionsBuilder builderProcessInstance = new SearchOptionsBuilder(0,10000)
builderProcessInstance.filter(ProcessInstanceSearchDescriptor.PROCESS_DEFINITION_ID,process.getProcessId())
final SearchResult<ProcessInstance> processInstanceResult = apiAccessor.getProcessAPI().searchProcessInstances(builderProcessInstance.done())
//POUR CHAQUE CASE TROUVÉ---------------------------------------------
for(final processInstance : processInstanceResult.getResult()) {
//ON CONSTRUIT LA RECHERCHE DES TACHES AVEC CASE_ID = CASE TROUVÉ---------------------------------------------
final SearchOptionsBuilder builderFlownode = new SearchOptionsBuilder(0,10000)
builderFlownode.filter(FlowNodeInstanceSearchDescriptor.ROOT_PROCESS_INSTANCE_ID, processInstance.rootProcessInstanceId)
builderFlownode.filter(FlowNodeInstanceSearchDescriptor.NAME, "C2 - Calcul numérotation")
final SearchResult<FlowNodeInstance> flownodeInstanceResult = apiAccessor.getProcessAPI().searchFlowNodeInstances(builderFlownode.done())
if (flownodeInstanceResult != null && flownodeInstanceResult.getCount() > 0) {
return true
}else{
return false
}
}
}
return false
Bonitasoft empowers development teams with Bonita, the open-source and extensible platform to solve the most demanding process automation use cases. The Bonita platform accelerates delivery of complex applications with clear separation between capabilities for visual programming and for coding. Bonita integrates with existing solutions, orchestrates heterogeneous systems, and provides deep visibility into processes across the organization.