BPM style entegrasyon

BPM style entegrasyon

Hi Habr!

Konpayi nou an espesyalize nan devlopman nan ERP-klas solisyon lojisyèl, pati lyon an nan yo ki okipe pa sistèm tranzaksyon ak yon kantite lajan gwo lojik biznis ak koule dokiman a la EDMS. Vèsyon aktyèl pwodwi nou yo baze sou teknoloji JavaEE, men n ap fè eksperyans aktivman ak mikwosèvis tou. Youn nan zòn ki pi pwoblèm nan solisyon sa yo se entegrasyon nan divès subsistèm ki fè pati domèn adjasan. Pwoblèm entegrasyon yo te toujou ban nou yon gwo tèt fè mal, kèlkeswa estil achitekti, pil teknoloji ak kad nou itilize, men dènyèman te gen pwogrè nan rezoud pwoblèm sa yo.

Nan atik mwen pote nan atansyon ou a, mwen pral pale sou eksperyans ak rechèch achitekti ke NPO Krista genyen nan zòn ki deziyen an. Nou pral gade tou nan yon egzanp yon solisyon senp nan yon pwoblèm entegrasyon nan pwen de vi nan yon devlopè aplikasyon epi chèche konnen ki sa ki kache dèyè senplisite sa a.

Limit responsabilite nou

Solisyon achitekti ak teknik ki dekri nan atik la yo pwopoze pa mwen ki baze sou eksperyans pèsonèl nan yon kontèks travay espesifik. Solisyon sa yo pa fè reklamasyon yo dwe inivèsèl epi yo ka pa pi bon nan lòt kondisyon pou itilize.

Kisa BPM gen pou wè ak li?

Pou reponn kesyon sa a, nou bezwen fouye yon ti kras pi fon nan spesifik yo nan pwoblèm yo aplike nan solisyon nou yo. Pati prensipal la nan lojik biznis la nan sistèm tranzaksyon tipik nou an se antre done nan baz done a atravè entèfas itilizatè, verifikasyon manyèl ak otomatik nan done sa yo, pote li soti nan kèk workflow, pibliye li nan yon lòt sistèm / baz done analyse / achiv, jenere rapò. . Se konsa, fonksyon kle nan sistèm nan pou kliyan se automatisation nan pwosesis biznis entèn yo.

Pou konvenyans, nou itilize tèm "dokiman an" nan kominikasyon kòm kèk abstraksyon nan yon seri done ini pa yon kle komen ak yon sèten workflow ka "lye".
Men, sa ki sou lojik entegrasyon? Apre yo tout, travay la entegrasyon ki te pwodwi pa achitekti nan sistèm nan, ki se "koupe" an pati PA sou demann kliyan an, men anba enfliyans nan faktè konplètman diferan:

  • sijè a lwa Conway a;
  • kòm yon rezilta nan reitilize subsystems deja devlope pou lòt pwodwi yo;
  • nan diskresyon achitèk la, ki baze sou kondisyon ki pa fonksyonèl.

Gen yon gwo tantasyon separe lojik entegrasyon soti nan lojik biznis nan workflow prensipal la, se konsa yo pa polye lojik biznis la ak zafè entegrasyon epi sove pwomotè aplikasyon an soti nan bezwen nan fouye nan karakteristik yo nan jaden flè a achitekti nan sistèm nan. Apwòch sa a gen yon kantite avantaj, men pratik montre inefikas li yo:

  • rezoud pwoblèm entegrasyon anjeneral tonbe tounen nan opsyon ki pi senp nan fòm lan nan apèl synchrone akòz pwen yo ekspansyon limite nan aplikasyon an nan workflow prensipal la (dezavantaj yo nan entegrasyon synchrone yo diskite anba a);
  • zafè entegrasyon toujou antre nan lojik biznis debaz lè yo mande fidbak nan yon lòt subsistèm;
  • pwomotè aplikasyon an inyore entegrasyon an epi li ka fasilman kraze li pa chanje workflow la;
  • sistèm nan sispann yo dwe yon sèl antye soti nan pwen de vi itilizatè a, "koud" ant subsystems vin aparan, ak operasyon redondants itilizatè parèt, kòmanse transfè a nan done ki sòti nan yon subsistèm nan yon lòt.

Yon lòt apwòch se konsidere entèraksyon entegrasyon kòm yon pati entegral nan lojik biznis debaz ak workflow. Pou anpeche kalifikasyon devlopè aplikasyon an monte, kreye nouvo entèraksyon entegrasyon yo ta dwe fasil epi san efò, ak opòtinite minimòm pou chwazi yon solisyon. Sa a se pi difisil pou fè pase sa li sanble: zouti a dwe ase pwisan pou bay itilizatè a varyete opsyon ki nesesè pou itilize li, san yo pa pèmèt li "tire tèt li nan pye a." Gen anpil kesyon ke yon enjenyè dwe reponn nan yon kontèks travay entegrasyon, men ke yon devlopè aplikasyon pa ta dwe reflechi sou nan travay chak jou li: limit tranzaksyon, konsistans, atomite, sekirite, dekale, chaj ak distribisyon resous, routage, marshaling, distribisyon ak chanje kontèks, elatriye Li nesesè yo ofri devlopè aplikasyon modèl solisyon jistis senp nan ki repons yo nan tout kesyon sa yo deja kache. Modèl sa yo dwe byen an sekirite: lojik biznis chanje trè souvan, ki ogmante risk pou yo entwodwi erè, pri a nan erè yo dwe rete nan yon nivo jistis ba.

Men, kisa BPM gen pou wè ak li? Gen anpil opsyon pou aplike workflow...
Vreman vre, yon lòt aplikasyon nan pwosesis biznis trè popilè nan solisyon nou yo - atravè definisyon an deklaratif nan yon dyagram tranzisyon eta ak koneksyon an nan moun kap okipe yo ak lojik biznis pou tranzisyon yo. Nan ka sa a, eta a ki detèmine pozisyon aktyèl la nan "dokiman an" nan pwosesis biznis la se yon atribi nan "dokiman an" tèt li.

BPM style entegrasyon
Sa a se sa pwosesis la sanble nan kòmansman an nan yon pwojè

Popilarite aplikasyon sa a se akòz senplisite relatif la ak vitès nan kreye pwosesis biznis lineyè. Sepandan, kòm sistèm lojisyèl toujou vin pi konplèks, pati otomatik nan pwosesis biznis la ap grandi epi li vin pi konplèks. Gen yon bezwen pou dekonpozisyon, reutilize pati nan pwosesis, osi byen ke pwosesis branch pou chak branch egzekite nan paralèl. Nan kondisyon sa yo, zouti a vin enkonvenyan, ak dyagram tranzisyon eta a pèdi kontni enfòmasyon li yo (enteraksyon entegrasyon yo pa reflete nan dyagram nan ditou).

BPM style entegrasyon
Sa a se sa pwosesis la sanble apre plizyè iterasyon nan klarifikasyon kondisyon.

Wout la soti nan sitiyasyon sa a te entegrasyon an nan motè a jBPM nan kèk pwodwi ak pwosesis biznis ki pi konplèks. Nan kout tèm, solisyon sa a te gen kèk siksè: li te vin posib aplike pwosesis biznis konplèks pandan y ap kenbe yon dyagram san patipri enfòmatif ak enpòtan nan notasyon an. BPMN2.

BPM style entegrasyon
Yon ti pati nan yon pwosesis biznis konplèks

Nan tèm long la, solisyon an pa t 'viv jiska atant: entansite nan travay segondè nan kreye pwosesis biznis atravè zouti vizyèl pa te pèmèt reyalize endikatè pwodiktivite akseptab, ak zouti nan tèt li te vin youn nan pi renmen nan mitan devlopè yo. Te gen tou plent sou estrikti entèn motè a, ki te mennen nan aparans nan anpil "patch" ak "beki".

Prensipal aspè pozitif lè w sèvi ak jBPM se te konsyans de benefis ak enkonvenyans ki genyen nan gen pwòp eta pèsistan yon egzanp pwosesis biznis. Nou te wè tou posiblite pou itilize yon apwòch pwosesis pou aplike pwotokòl entegrasyon konplèks ant aplikasyon diferan lè l sèvi avèk entèraksyon asynchrone atravè siyal ak mesaj. Prezans yon eta ki pèsistan jwe yon wòl enpòtan nan sa.

Dapre sa ki anwo a, nou ka konkli: Apwòch pwosesis la nan style la BPM pèmèt nou rezoud yon pakèt travay nan otomatize pwosesis biznis de pli zan pli konplèks, annamoni anfòm aktivite entegrasyon nan pwosesis sa yo epi kenbe kapasite nan vizyèlman montre pwosesis la aplike nan yon notasyon apwopriye.

Dezavantaj nan apèl synchrone kòm yon modèl entegrasyon

Entegrasyon synchrone refere a apèl ki pi senp bloke. Yon subsistèm aji kòm bò sèvè a epi li ekspoze API a ak metòd ki nesesè yo. Yon lòt subsistèm aji kòm bò kliyan ak nan bon moman fè yon apèl epi tann pou rezilta a. Tou depan de achitekti sistèm lan, kote kliyan ak sèvè yo ka lokalize swa nan menm aplikasyon an ak pwosesis, oswa nan diferan. Nan dezyèm ka a, ou bezwen aplike kèk aplikasyon RPC epi bay marshalling nan paramèt yo ak rezilta apèl la.

BPM style entegrasyon

Modèl entegrasyon sa a gen yon seri dezavantaj jistis gwo, men li trè lajman itilize nan pratik akòz senplisite li yo. Vitès aplikasyon an kaptive ak fòse ou sèvi ak li ankò e ankò nan fè fas a dat limit peze, anrejistreman solisyon an kòm dèt teknik. Men, li rive tou ke devlopè san eksperyans sèvi ak li enkonsyaman, tou senpleman pa reyalize konsekans negatif yo.

Anplis ogmantasyon ki pi evidan nan koneksyon subsistèm yo, genyen tou pwoblèm mwens evidan ak tranzaksyon "ap grandi" ak "etann". Vreman vre, si lojik biznis la fè kèk chanjman, Lè sa a, tranzaksyon yo pa ka evite, ak tranzaksyon yo, nan vire, bloke sèten resous aplikasyon ki afekte nan chanjman sa yo. Sa vle di, jiskaske yon sous-sistèm tann pou yon repons nan men lòt la, li pa pral kapab konplete tranzaksyon an epi retire kadna yo. Sa a siyifikativman ogmante risk pou yon varyete de efè:

  • Se repons nan sistèm nan pèdi, itilizatè yo tann yon bon bout tan pou repons a demann;
  • sèvè a jeneralman sispann reponn a demann itilizatè akòz yon pisin fil ki gen twòp elèv: majorite fil yo fèmen sou yon resous okipe pa yon tranzaksyon;
  • Deadlocks kòmanse parèt: chans pou ensidan yo depann anpil sou dire tranzaksyon yo, kantite lajan an nan lojik biznis ak kadna ki enplike nan tranzaksyon an;
  • erè timeout tranzaksyon parèt;
  • sèvè a "echwe" ak OutOfMemory si travay la mande pou trete ak chanje gwo kantite done, ak prezans nan entegrasyon synchrone fè li trè difisil divize pwosesis nan tranzaksyon "pi lejè".

Soti nan yon pwen de vi achitekti, itilize nan bloke apèl pandan entegrasyon mennen nan yon pèt kontwòl sou bon jan kalite a nan subsistèm endividyèl yo: li enposib asire endikatè yo bon jan kalite sib nan yon subsistèm nan izolasyon ak endikatè yo bon jan kalite nan yon lòt subsistèm. Si subsistèm yo devlope pa ekip diferan, sa a se yon gwo pwoblèm.

Bagay yo vin pi enteresan toujou si sistèm yo entegre yo nan aplikasyon diferan epi ou bezwen fè chanjman synchrone sou tou de bò yo. Ki jan yo asire tranzaksyon an nan chanjman sa yo?

Si chanjman yo fèt nan tranzaksyon separe, Lè sa a, w ap bezwen bay yon seri eksepsyon serye ak konpansasyon, e sa konplètman elimine avantaj prensipal la nan entegrasyon synchrone - senplisite.

Tranzaksyon distribye tou vin nan tèt ou, men nou pa sèvi ak yo nan solisyon nou yo: li difisil asire fyab.

"Saga" kòm yon solisyon nan pwoblèm nan tranzaksyon

Avèk popilarite a ap grandi nan mikwosèvis, demann lan pou Modèl lejand.

Modèl sa a parfe rezoud pwoblèm ki mansyone anwo a nan tranzaksyon long, epi tou li elaji kapasite yo nan jere eta a nan sistèm nan soti nan bò a nan lojik biznis: konpansasyon apre yon tranzaksyon echwe pa ka woule tounen sistèm nan eta orijinal li, men bay. yon wout altènatif tretman done. Sa a tou pèmèt ou evite repete etap pwosesis done konplete avèk siksè lè w ap eseye mennen pwosesis la nan yon "bon" fini.

Enteresan, nan sistèm monolitik modèl sa a enpòtan tou lè li rive entegrasyon nan subsystems ki lach makonnen ak efè negatif ki te koze pa tranzaksyon ki dire lontan ak kadna resous korespondan yo obsève.

An relasyon ak pwosesis biznis nou yo nan style BPM, li sanble trè fasil pou aplike "Sagas": etap endividyèl "Saga" yo ka espesifye kòm aktivite nan pwosesis biznis la, ak eta ki pèsistan nan pwosesis biznis la tou. detèmine eta entèn "Saga la". Sa vle di, nou pa bezwen okenn mekanis kowòdinasyon adisyonèl. Tout sa ou bezwen se yon koutye mesaj ki sipòte "omwen yon fwa" garanti kòm yon transpò.

Men, solisyon sa a tou gen pwòp "pri" li yo:

  • lojik biznis vin pi konplèks: konpansasyon bezwen yo dwe travay deyò;
  • li pral nesesè yo abandone konsistans konplè, ki ka espesyalman sansib pou sistèm monolitik;
  • Achitekti a vin yon ti kras pi konplike, ak yon bezwen adisyonèl pou yon koutye mesaj parèt;
  • siveyans adisyonèl ak zouti administrasyon yo pral mande (byenke an jeneral sa a se yon bon bagay: bon jan kalite a nan sèvis sistèm ap ogmante).

Pou sistèm monolitik, jistifikasyon pou itilize "Sag" pa tèlman evidan. Pou mikwosèvis ak lòt SOA, kote gen plis chans deja gen yon koutye, epi yo sakrifye konsistans konplè nan kòmansman pwojè a, benefis ki genyen nan sèvi ak modèl sa a ka siyifikativman depase dezavantaj yo, espesyalman si gen yon API pratik nan lojik biznis la. nivo.

Encapsulation lojik biznis nan microservices

Lè nou te kòmanse fè eksperyans ak mikwosèvis, yon kesyon rezonab te parèt: ki kote yo mete lojik biznis la domèn an relasyon ak sèvis la ki asire pèsistans nan done domèn?

Lè w ap gade achitekti divès kalite BPMS yo, li ka sanble rezonab pou separe lojik biznis ak pèsistans: kreye yon kouch platfòm ak mikwosèvis endepandan ki fòme yon anviwònman ak veso pou egzekite lojik biznis domèn, epi konsepsyon pèsistans done domèn yo jan. yon kouch separe nan mikwosèvis trè senp ak ki lejè. Nan ka sa a, pwosesis biznis òkestre sèvis yo nan kouch pèsistans yap ogmante jiska.

BPM style entegrasyon

Apwòch sa a gen yon gwo avantaj: ou ka ogmante fonksyonalite platfòm la otan ou vle, epi sèlman kouch korespondan mikwosèvis platfòm la ap vin "grès" nan sa a. Pwosesis biznis ki soti nan nenpòt domèn imedyatman kapab itilize nouvo fonksyonalite platfòm la le pli vit ke li mete ajou.

Yon etid pi detaye revele dezavantaj enpòtan nan apwòch sa a:

  • yon sèvis platfòm ki egzekite lojik biznis nan anpil domèn nan yon fwa pote gwo risk kòm yon sèl pwen echèk. Chanjman souvan nan lojik biznis ogmante risk erè ki mennen nan echèk nan tout sistèm;
  • pwoblèm pèfòmans: lojik biznis travay ak done li yo atravè yon koòdone etwat ak dousman:
    • done yo pral yon lòt fwa ankò dwe rasanble ak ponpe atravè chemine rezo a;
    • yon sèvis domèn pral souvan bay plis done pase sa nesesè pou lojik biznis yo trete akòz kapasite ensifizan pou paramèt demann nan nivo API ekstèn nan sèvis la;
    • plizyè moso endepandan nan lojik biznis ka repete re-mande menm done yo pou tretman (pwoblèm sa a ka bese lè yo ajoute konpozan sesyon ki done kachèt, men sa a plis konplike achitekti a ak kreye pwoblèm nan enpòtans done ak envalidasyon kachèt);
  • pwoblèm tranzaksyon:
    • pwosesis biznis ak eta pèsistan, ki estoke pa yon sèvis platfòm, yo enkonsistan ak done domèn, epi pa gen okenn fason fasil yo rezoud pwoblèm sa a;
    • mete domèn done bloke deyò tranzaksyon an: si lojik biznis la domèn bezwen fè chanjman apre premye tcheke kòrèkteman nan done aktyèl yo, li nesesè yo eskli posibilite pou yon chanjman konpetitif nan done yo trete. Bloke done ekstèn ka ede rezoud pwoblèm nan, men yon solisyon sa yo pote risk adisyonèl ak diminye fyab la an jeneral nan sistèm nan;
  • difikilte adisyonèl lè mete ajou: nan kèk ka, sèvis la pèsistans ak lojik biznis bezwen mete ajou synchrone oswa nan sekans strik.

Finalman, nou te oblije tounen nan baz: ankapsile done domèn ak lojik biznis domèn nan yon sèl mikwosèvis. Apwòch sa a senplifye pèsepsyon yon mikwosèvis kòm yon eleman entegral nan sistèm nan epi li pa bay monte pwoblèm ki anwo yo. Sa a pa bay tou gratis:

  • Normalizasyon API obligatwa pou entèraksyon ak lojik biznis (an patikilye, pou bay aktivite itilizatè yo kòm yon pati nan pwosesis biznis) ak sèvis platfòm API; mande plis atansyon sou chanjman API, konpatibilite pou pi devan ak bak;
  • li nesesè pou ajoute bibliyotèk adisyonèl pou asire fonksyone lojik biznis kòm yon pati nan chak mikwosèvis sa yo, e sa bay nouvo kondisyon pou bibliyotèk sa yo: lejè ak yon minimòm depandans tranzitif;
  • devlopè lojik biznis yo bezwen kontwole vèsyon bibliyotèk yo: si yon mikwosèvis pa te finalize pou yon tan long, Lè sa a, li pral gen plis chans gen yon vèsyon demode nan bibliyotèk yo. Sa a ka yon obstak inatandi pou ajoute yon nouvo karakteristik epi li ka mande pou imigre lojik biznis ansyen nan sèvis sa a nan nouvo vèsyon bibliyotèk si te gen chanjman enkonpatib ant vèsyon yo.

BPM style entegrasyon

Yon kouch sèvis platfòm tou prezan nan yon achitekti konsa, men kouch sa a pa fòme yon veso ankò pou egzekite lojik biznis domèn, men se sèlman anviwònman li yo, ki bay fonksyon oksilyè "platfòm". Yon kouch sa a nesesè non sèlman pou kenbe nati ki lejè nan mikwosèvis domèn, men tou pou santralize jesyon.

Pou egzanp, aktivite itilizatè nan pwosesis biznis jenere travay. Sepandan, lè w ap travay ak travay, itilizatè a dwe wè travay ki soti nan tout domèn nan lis jeneral la, ki vle di dwe gen yon sèvis enskripsyon travay platfòm korespondan, otorize nan lojik biznis domèn. Kenbe enkapsulasyon nan lojik biznis nan yon kontèks se byen pwoblèm, e sa a se yon lòt konpwomi nan achitekti sa a.

Entegrasyon nan pwosesis biznis nan je yo nan yon pwomotè aplikasyon

Kòm mansyone pi wo a, yon devlopè aplikasyon dwe abstrè soti nan karakteristik yo ki teknik ak jeni nan aplikasyon entèraksyon an nan plizyè aplikasyon pou ke yon moun ka konte sou pwodiktivite devlopman bon.

Ann eseye rezoud yon pwoblèm entegrasyon olye difisil, espesyalman envante pou atik la. Sa a pral yon travay "jwèt" ki enplike twa aplikasyon, kote chak nan yo defini yon sèten non domèn: "app1", "app2", "app3".

Anndan chak aplikasyon, pwosesis biznis yo lanse ki kòmanse "jwe boul" atravè otobis entegrasyon an. Mesaj ki gen non "Boul" pral aji kòm yon boul.

Règ nan jwèt la:

  • premye jwè a se inisyatè a. Li envite lòt jwè yo nan jwèt la, kòmanse jwèt la epi li ka fini li nenpòt ki lè;
  • lòt jwè yo deklare patisipasyon yo nan jwèt la, "fè konnen" youn ak lòt ak premye jwè a;
  • apre li fin resevwa boul la, jwè a chwazi yon lòt jwè k ap patisipe epi li pase boul la ba li. Kantite total transmisyon yo konte;
  • Chak jwè gen "enèji" ki diminye ak chak pase nan boul la pa jwè sa a. Lè enèji a fini, jwè a kite jwèt la, li anonse demisyon li;
  • si jwè a rete pou kont li, li imedyatman anonse depa li;
  • Lè tout jwè yo elimine, premye jwè a deklare jwèt la fini. Si li kite jwèt la byen bonè, li rete pou swiv jwèt la pou konplete li.

Pou rezoud pwoblèm sa a, mwen pral sèvi ak DSL nou an pou pwosesis biznis, ki pèmèt nou dekri lojik la nan Kotlin konpak, ak yon minimòm de boilerplate.

Pwosesis biznis premye jwè a (aka inisyatè jwèt la) ap travay nan aplikasyon app1:

klas InitialPlayer

import ru.krista.bpm.ProcessInstance
import ru.krista.bpm.runtime.ProcessImpl
import ru.krista.bpm.runtime.constraint.UniqueConstraints
import ru.krista.bpm.runtime.dsl.processModel
import ru.krista.bpm.runtime.dsl.taskOperation
import ru.krista.bpm.runtime.instance.MessageSendInstance

data class PlayerInfo(val name: String, val domain: String, val id: String)

class PlayersList : ArrayList<PlayerInfo>()

// Это класс экземпляра процесса: инкапсулирует его внутреннее состояние
class InitialPlayer : ProcessImpl<InitialPlayer>(initialPlayerModel) {
    var playerName: String by persistent("Player1")
    var energy: Int by persistent(30)
    var players: PlayersList by persistent(PlayersList())
    var shotCounter: Int = 0
}

// Это декларация модели процесса: создается один раз, используется всеми
// экземплярами процесса соответствующего класса
val initialPlayerModel = processModel<InitialPlayer>(name = "InitialPlayer",
                                                     version = 1) {

    // По правилам, первый игрок является инициатором игры и должен быть единственным
    uniqueConstraint = UniqueConstraints.singleton

    // Объявляем активности, из которых состоит бизнес-процесс
    val sendNewGameSignal = signal<String>("NewGame")
    val sendStopGameSignal = signal<String>("StopGame")
    val startTask = humanTask("Start") {
        taskOperation {
            processCondition { players.size > 0 }
            confirmation { "Подключилось ${players.size} игроков. Начинаем?" }
        }
    }
    val stopTask = humanTask("Stop") {
        taskOperation {}
    }
    val waitPlayerJoin = signalWait<String>("PlayerJoin") { signal ->
        players.add(PlayerInfo(
                signal.data!!,
                signal.sender.domain,
                signal.sender.processInstanceId))
        println("... join player ${signal.data} ...")
    }
    val waitPlayerOut = signalWait<String>("PlayerOut") { signal ->
        players.remove(PlayerInfo(
                signal.data!!,
                signal.sender.domain,
                signal.sender.processInstanceId))
        println("... player ${signal.data} is out ...")
    }
    val sendPlayerOut = signal<String>("PlayerOut") {
        signalData = { playerName }
    }
    val sendHandshake = messageSend<String>("Handshake") {
        messageData = { playerName }
        activation = {
            receiverDomain = process.players.last().domain
            receiverProcessInstanceId = process.players.last().id
        }
    }
    val throwStartBall = messageSend<Int>("Ball") {
        messageData = { 1 }
        activation = { selectNextPlayer() }
    }
    val throwBall = messageSend<Int>("Ball") {
        messageData = { shotCounter + 1 }
        activation = { selectNextPlayer() }
        onEntry { energy -= 1 }
    }
    val waitBall = messageWaitData<Int>("Ball") {
        shotCounter = it
    }

    // Теперь конструируем граф процесса из объявленных активностей
    startFrom(sendNewGameSignal)
            .fork("mainFork") {
                next(startTask)
                next(waitPlayerJoin).next(sendHandshake).next(waitPlayerJoin)
                next(waitPlayerOut)
                        .branch("checkPlayers") {
                            ifTrue { players.isEmpty() }
                                    .next(sendStopGameSignal)
                                    .terminate()
                            ifElse().next(waitPlayerOut)
                        }
            }
    startTask.fork("afterStart") {
        next(throwStartBall)
                .branch("mainLoop") {
                    ifTrue { energy < 5 }.next(sendPlayerOut).next(waitBall)
                    ifElse().next(waitBall).next(throwBall).loop()
                }
        next(stopTask).next(sendStopGameSignal)
    }

    // Навешаем на активности дополнительные обработчики для логирования
    sendNewGameSignal.onExit { println("Let's play!") }
    sendStopGameSignal.onExit { println("Stop!") }
    sendPlayerOut.onExit { println("$playerName: I'm out!") }
}

private fun MessageSendInstance<InitialPlayer, Int>.selectNextPlayer() {
    val player = process.players.random()
    receiverDomain = player.domain
    receiverProcessInstanceId = player.id
    println("Step ${process.shotCounter + 1}: " +
            "${process.playerName} >>> ${player.name}")
}

Anplis de sa nan egzekite lojik biznis, kòd ki anwo a ka pwodwi yon modèl objè nan yon pwosesis biznis, ki ka visualized nan fòm lan nan yon dyagram. Nou poko aplike vizyalize a, kidonk nou te oblije pase yon ti tan pou fè desen (isit la mwen yon ti kras senplifye notasyon BPMN konsènan itilizasyon pòtay yo pou amelyore konsistans dyagram nan ak kòd ki anba a):

BPM style entegrasyon

app2 pral gen ladan pwosesis biznis lòt jwè a:

klas RandomPlayer

import ru.krista.bpm.ProcessInstance
import ru.krista.bpm.runtime.ProcessImpl
import ru.krista.bpm.runtime.dsl.processModel
import ru.krista.bpm.runtime.instance.MessageSendInstance

data class PlayerInfo(val name: String, val domain: String, val id: String)

class PlayersList: ArrayList<PlayerInfo>()

class RandomPlayer : ProcessImpl<RandomPlayer>(randomPlayerModel) {

    var playerName: String by input(persistent = true, 
                                    defaultValue = "RandomPlayer")
    var energy: Int by input(persistent = true, defaultValue = 30)
    var players: PlayersList by persistent(PlayersList())
    var allPlayersOut: Boolean by persistent(false)
    var shotCounter: Int = 0

    val selfPlayer: PlayerInfo
        get() = PlayerInfo(playerName, env.eventDispatcher.domainName, id)
}

val randomPlayerModel = processModel<RandomPlayer>(name = "RandomPlayer", 
                                                   version = 1) {

    val waitNewGameSignal = signalWait<String>("NewGame")
    val waitStopGameSignal = signalWait<String>("StopGame")
    val sendPlayerJoin = signal<String>("PlayerJoin") {
        signalData = { playerName }
    }
    val sendPlayerOut = signal<String>("PlayerOut") {
        signalData = { playerName }
    }
    val waitPlayerJoin = signalWaitCustom<String>("PlayerJoin") {
        eventCondition = { signal ->
            signal.sender.processInstanceId != process.id 
                && !process.players.any { signal.sender.processInstanceId == it.id}
        }
        handler = { signal ->
            players.add(PlayerInfo(
                    signal.data!!,
                    signal.sender.domain,
                    signal.sender.processInstanceId))
        }
    }
    val waitPlayerOut = signalWait<String>("PlayerOut") { signal ->
        players.remove(PlayerInfo(
                signal.data!!,
                signal.sender.domain,
                signal.sender.processInstanceId))
        allPlayersOut = players.isEmpty()
    }
    val sendHandshake = messageSend<String>("Handshake") {
        messageData = { playerName }
        activation = {
            receiverDomain = process.players.last().domain
            receiverProcessInstanceId = process.players.last().id
        }
    }
    val receiveHandshake = messageWait<String>("Handshake") { message ->
        if (!players.any { message.sender.processInstanceId == it.id}) {
            players.add(PlayerInfo(
                    message.data!!, 
                    message.sender.domain, 
                    message.sender.processInstanceId))
        }
    }
    val throwBall = messageSend<Int>("Ball") {
        messageData = { shotCounter + 1 }
        activation = { selectNextPlayer() }
        onEntry { energy -= 1 }
    }
    val waitBall = messageWaitData<Int>("Ball") {
        shotCounter = it
    }

    startFrom(waitNewGameSignal)
            .fork("mainFork") {
                next(sendPlayerJoin)
                        .branch("mainLoop") {
                            ifTrue { energy < 5 || allPlayersOut }
                                    .next(sendPlayerOut)
                                    .next(waitBall)
                            ifElse()
                                    .next(waitBall)
                                    .next(throwBall)
                                    .loop()
                        }
                next(waitPlayerJoin).next(sendHandshake).next(waitPlayerJoin)
                next(waitPlayerOut).next(waitPlayerOut)
                next(receiveHandshake).next(receiveHandshake)
                next(waitStopGameSignal).terminate()
            }

    sendPlayerJoin.onExit { println("$playerName: I'm here!") }
    sendPlayerOut.onExit { println("$playerName: I'm out!") }
}

private fun MessageSendInstance<RandomPlayer, Int>.selectNextPlayer() {
    val player = if (process.players.isNotEmpty()) 
        process.players.random() 
    else 
        process.selfPlayer
    receiverDomain = player.domain
    receiverProcessInstanceId = player.id
    println("Step ${process.shotCounter + 1}: " +
            "${process.playerName} >>> ${player.name}")
}

Dyagram:

BPM style entegrasyon

Nan aplikasyon app3 a nou pral fè yon jwè ki gen yon konpòtman yon ti kras diferan: olye pou yo chwazi pwochen jwè a owaza, li pral aji dapre algorithm round-robin la:

klas RoundRobinPlayer

import ru.krista.bpm.ProcessInstance
import ru.krista.bpm.runtime.ProcessImpl
import ru.krista.bpm.runtime.dsl.processModel
import ru.krista.bpm.runtime.instance.MessageSendInstance

data class PlayerInfo(val name: String, val domain: String, val id: String)

class PlayersList: ArrayList<PlayerInfo>()

class RoundRobinPlayer : ProcessImpl<RoundRobinPlayer>(roundRobinPlayerModel) {

    var playerName: String by input(persistent = true, 
                                    defaultValue = "RoundRobinPlayer")
    var energy: Int by input(persistent = true, defaultValue = 30)
    var players: PlayersList by persistent(PlayersList())
    var nextPlayerIndex: Int by persistent(-1)
    var allPlayersOut: Boolean by persistent(false)
    var shotCounter: Int = 0

    val selfPlayer: PlayerInfo
        get() = PlayerInfo(playerName, env.eventDispatcher.domainName, id)
}

val roundRobinPlayerModel = processModel<RoundRobinPlayer>(
        name = "RoundRobinPlayer", 
        version = 1) {

    val waitNewGameSignal = signalWait<String>("NewGame")
    val waitStopGameSignal = signalWait<String>("StopGame")
    val sendPlayerJoin = signal<String>("PlayerJoin") {
        signalData = { playerName }
    }
    val sendPlayerOut = signal<String>("PlayerOut") {
        signalData = { playerName }
    }
    val waitPlayerJoin = signalWaitCustom<String>("PlayerJoin") {
        eventCondition = { signal ->
            signal.sender.processInstanceId != process.id 
                && !process.players.any { signal.sender.processInstanceId == it.id}
        }
        handler = { signal ->
            players.add(PlayerInfo(
                    signal.data!!, 
                    signal.sender.domain, 
                    signal.sender.processInstanceId))
        }
    }
    val waitPlayerOut = signalWait<String>("PlayerOut") { signal ->
        players.remove(PlayerInfo(
                signal.data!!, 
                signal.sender.domain, 
                signal.sender.processInstanceId))
        allPlayersOut = players.isEmpty()
    }
    val sendHandshake = messageSend<String>("Handshake") {
        messageData = { playerName }
        activation = {
            receiverDomain = process.players.last().domain
            receiverProcessInstanceId = process.players.last().id
        }
    }
    val receiveHandshake = messageWait<String>("Handshake") { message ->
        if (!players.any { message.sender.processInstanceId == it.id}) {
            players.add(PlayerInfo(
                    message.data!!, 
                    message.sender.domain, 
                    message.sender.processInstanceId))
        }
    }
    val throwBall = messageSend<Int>("Ball") {
        messageData = { shotCounter + 1 }
        activation = { selectNextPlayer() }
        onEntry { energy -= 1 }
    }
    val waitBall = messageWaitData<Int>("Ball") {
        shotCounter = it
    }

    startFrom(waitNewGameSignal)
            .fork("mainFork") {
                next(sendPlayerJoin)
                        .branch("mainLoop") {
                            ifTrue { energy < 5 || allPlayersOut }
                                    .next(sendPlayerOut)
                                    .next(waitBall)
                            ifElse()
                                    .next(waitBall)
                                    .next(throwBall)
                                    .loop()
                        }
                next(waitPlayerJoin).next(sendHandshake).next(waitPlayerJoin)
                next(waitPlayerOut).next(waitPlayerOut)
                next(receiveHandshake).next(receiveHandshake)
                next(waitStopGameSignal).terminate()
            }

    sendPlayerJoin.onExit { println("$playerName: I'm here!") }
    sendPlayerOut.onExit { println("$playerName: I'm out!") }
}

private fun MessageSendInstance<RoundRobinPlayer, Int>.selectNextPlayer() {
    var idx = process.nextPlayerIndex + 1
    if (idx >= process.players.size) {
        idx = 0
    }
    process.nextPlayerIndex = idx
    val player = if (process.players.isNotEmpty()) 
        process.players[idx] 
    else 
        process.selfPlayer
    receiverDomain = player.domain
    receiverProcessInstanceId = player.id
    println("Step ${process.shotCounter + 1}: " +
            "${process.playerName} >>> ${player.name}")
}

Sinon, konpòtman jwè a pa diferan de youn anvan an, kidonk dyagram nan pa chanje.

Koulye a, nou bezwen yon tès pou kouri tout bagay sa yo. Mwen pral bay sèlman kòd la nan tès la tèt li, pou yo pa ankonbre atik la ak yon boilerplate (an reyalite, mwen te itilize anviwònman tès la te kreye pi bonè yo teste entegrasyon an nan lòt pwosesis biznis):

testGame()

@Test
public void testGame() throws InterruptedException {
    String pl2 = startProcess(app2, "RandomPlayer", playerParams("Player2", 20));
    String pl3 = startProcess(app2, "RandomPlayer", playerParams("Player3", 40));
    String pl4 = startProcess(app3, "RoundRobinPlayer", playerParams("Player4", 25));
    String pl5 = startProcess(app3, "RoundRobinPlayer", playerParams("Player5", 35));
    String pl1 = startProcess(app1, "InitialPlayer");
    // Теперь нужно немного подождать, пока игроки "познакомятся" друг с другом.
    // Ждать через sleep - плохое решение, зато самое простое. 
    // Не делайте так в серьезных тестах!
    Thread.sleep(1000);
    // Запускаем игру, закрывая пользовательскую активность
    assertTrue(closeTask(app1, pl1, "Start"));
    app1.getWaiting().waitProcessFinished(pl1);
    app2.getWaiting().waitProcessFinished(pl2);
    app2.getWaiting().waitProcessFinished(pl3);
    app3.getWaiting().waitProcessFinished(pl4);
    app3.getWaiting().waitProcessFinished(pl5);
}

private Map<String, Object> playerParams(String name, int energy) {
    Map<String, Object> params = new HashMap<>();
    params.put("playerName", name);
    params.put("energy", energy);
    return params;
}

Ann kouri tès la epi gade nan boutèy la:

pwodiksyon konsole

Взята блокировка ключа lock://app1/process/InitialPlayer
Let's play!
Снята блокировка ключа lock://app1/process/InitialPlayer
Player2: I'm here!
Player3: I'm here!
Player4: I'm here!
Player5: I'm here!
... join player Player2 ...
... join player Player4 ...
... join player Player3 ...
... join player Player5 ...
Step 1: Player1 >>> Player3
Step 2: Player3 >>> Player5
Step 3: Player5 >>> Player3
Step 4: Player3 >>> Player4
Step 5: Player4 >>> Player3
Step 6: Player3 >>> Player4
Step 7: Player4 >>> Player5
Step 8: Player5 >>> Player2
Step 9: Player2 >>> Player5
Step 10: Player5 >>> Player4
Step 11: Player4 >>> Player2
Step 12: Player2 >>> Player4
Step 13: Player4 >>> Player1
Step 14: Player1 >>> Player4
Step 15: Player4 >>> Player3
Step 16: Player3 >>> Player1
Step 17: Player1 >>> Player2
Step 18: Player2 >>> Player3
Step 19: Player3 >>> Player1
Step 20: Player1 >>> Player5
Step 21: Player5 >>> Player1
Step 22: Player1 >>> Player2
Step 23: Player2 >>> Player4
Step 24: Player4 >>> Player5
Step 25: Player5 >>> Player3
Step 26: Player3 >>> Player4
Step 27: Player4 >>> Player2
Step 28: Player2 >>> Player5
Step 29: Player5 >>> Player2
Step 30: Player2 >>> Player1
Step 31: Player1 >>> Player3
Step 32: Player3 >>> Player4
Step 33: Player4 >>> Player1
Step 34: Player1 >>> Player3
Step 35: Player3 >>> Player4
Step 36: Player4 >>> Player3
Step 37: Player3 >>> Player2
Step 38: Player2 >>> Player5
Step 39: Player5 >>> Player4
Step 40: Player4 >>> Player5
Step 41: Player5 >>> Player1
Step 42: Player1 >>> Player5
Step 43: Player5 >>> Player3
Step 44: Player3 >>> Player5
Step 45: Player5 >>> Player2
Step 46: Player2 >>> Player3
Step 47: Player3 >>> Player2
Step 48: Player2 >>> Player5
Step 49: Player5 >>> Player4
Step 50: Player4 >>> Player2
Step 51: Player2 >>> Player5
Step 52: Player5 >>> Player1
Step 53: Player1 >>> Player5
Step 54: Player5 >>> Player3
Step 55: Player3 >>> Player5
Step 56: Player5 >>> Player2
Step 57: Player2 >>> Player1
Step 58: Player1 >>> Player4
Step 59: Player4 >>> Player1
Step 60: Player1 >>> Player4
Step 61: Player4 >>> Player3
Step 62: Player3 >>> Player2
Step 63: Player2 >>> Player5
Step 64: Player5 >>> Player4
Step 65: Player4 >>> Player5
Step 66: Player5 >>> Player1
Step 67: Player1 >>> Player5
Step 68: Player5 >>> Player3
Step 69: Player3 >>> Player4
Step 70: Player4 >>> Player2
Step 71: Player2 >>> Player5
Step 72: Player5 >>> Player2
Step 73: Player2 >>> Player1
Step 74: Player1 >>> Player4
Step 75: Player4 >>> Player1
Step 76: Player1 >>> Player2
Step 77: Player2 >>> Player5
Step 78: Player5 >>> Player4
Step 79: Player4 >>> Player3
Step 80: Player3 >>> Player1
Step 81: Player1 >>> Player5
Step 82: Player5 >>> Player1
Step 83: Player1 >>> Player4
Step 84: Player4 >>> Player5
Step 85: Player5 >>> Player3
Step 86: Player3 >>> Player5
Step 87: Player5 >>> Player2
Step 88: Player2 >>> Player3
Player2: I'm out!
Step 89: Player3 >>> Player4
... player Player2 is out ...
Step 90: Player4 >>> Player1
Step 91: Player1 >>> Player3
Step 92: Player3 >>> Player1
Step 93: Player1 >>> Player4
Step 94: Player4 >>> Player3
Step 95: Player3 >>> Player5
Step 96: Player5 >>> Player1
Step 97: Player1 >>> Player5
Step 98: Player5 >>> Player3
Step 99: Player3 >>> Player5
Step 100: Player5 >>> Player4
Step 101: Player4 >>> Player5
Player4: I'm out!
... player Player4 is out ...
Step 102: Player5 >>> Player1
Step 103: Player1 >>> Player3
Step 104: Player3 >>> Player1
Step 105: Player1 >>> Player3
Step 106: Player3 >>> Player5
Step 107: Player5 >>> Player3
Step 108: Player3 >>> Player1
Step 109: Player1 >>> Player3
Step 110: Player3 >>> Player5
Step 111: Player5 >>> Player1
Step 112: Player1 >>> Player3
Step 113: Player3 >>> Player5
Step 114: Player5 >>> Player3
Step 115: Player3 >>> Player1
Step 116: Player1 >>> Player3
Step 117: Player3 >>> Player5
Step 118: Player5 >>> Player1
Step 119: Player1 >>> Player3
Step 120: Player3 >>> Player5
Step 121: Player5 >>> Player3
Player5: I'm out!
... player Player5 is out ...
Step 122: Player3 >>> Player5
Step 123: Player5 >>> Player1
Player5: I'm out!
Step 124: Player1 >>> Player3
... player Player5 is out ...
Step 125: Player3 >>> Player1
Step 126: Player1 >>> Player3
Player1: I'm out!
... player Player1 is out ...
Step 127: Player3 >>> Player3
Player3: I'm out!
Step 128: Player3 >>> Player3
... player Player3 is out ...
Player3: I'm out!
Stop!
Step 129: Player3 >>> Player3
Player3: I'm out!

Apati tout bagay sa yo nou ka tire plizyè konklizyon enpòtan:

  • ak zouti ki nesesè yo, devlopè aplikasyon yo ka kreye entèraksyon entegrasyon ant aplikasyon yo san yo pa entèwonp lojik biznis;
  • ka konpleksite a nan yon travay entegrasyon ki mande konpetans jeni ka kache nan kad la si sa a se okòmansman enkli nan achitekti nan fondasyon an. Difikilte pou yon pwoblèm pa ka kache, kidonk solisyon an nan yon pwoblèm difisil nan kòd pral sanble ak li;
  • Lè w ap devlope lojik entegrasyon, li enperatif pou w pran an kont konsistans evantyèlman ak mank de linearizabilite chanjman nan eta tout patisipan entegrasyon yo. Sa a fòse nou konplike lojik la nan lòd yo fè li ensansib nan lòd la nan ki evènman ekstèn yo rive. Nan egzanp nou an, jwè a oblije patisipe nan jwèt la apre li te deklare sòti li nan jwèt la: lòt jwè yo ap kontinye pase boul la ba li jiskaske enfòmasyon sou sòti li rive nan epi yo trete pa tout patisipan yo. Lojik sa a pa swiv règ yo nan jwèt la epi li se yon solisyon konpwomi nan kad achitekti yo chwazi a.

Apre sa, nou pral pale sou divès kalite solisyon nou an, konpwomi ak lòt pwen.

Tout mesaj yo nan yon sèl keu

Tout aplikasyon entegre travay ak yon sèl otobis entegrasyon, ki prezante nan fòm lan nan yon koutye ekstèn, yon sèl BPMQueue pou mesaj ak yon sijè BPMTopic pou siyal (evènman). Mete tout mesaj nan yon sèl keu se tèt li yon konpwomi. Nan nivo lojik biznis la, ou kapab kounye a prezante kòm anpil nouvo kalite mesaj jan ou renmen san yo pa fè chanjman nan estrikti sistèm lan. Sa a se yon senplifikasyon enpòtan, men li pote sèten risk, ki nan yon kontèks travay tipik nou an pa t 'sanble tèlman enpòtan pou nou.

BPM style entegrasyon

Sepandan, gen yon sèl sibtilite isit la: chak aplikasyon filtre "li" mesaj ki soti nan keu la nan papòt la, pa non an nan domèn li yo. Domèn nan kapab tou espesifye nan siyal si ou bezwen limite "dimansyon de vizibilite" nan siyal la nan yon sèl aplikasyon. Sa a ta dwe ogmante debi otobis la, men lojik biznis la dwe kounye a opere ak non domèn: pou adrese mesaj - obligatwa, pou siyal - dezirab.

Asire Entegrasyon Bis Fyab

Fyab konsiste de plizyè pwen:

  • Koutye mesaj chwazi a se yon eleman kritik nan achitekti a ak yon sèl pwen nan echèk: li dwe ase fòt-toleran. Ou ta dwe itilize sèlman aplikasyon tan teste, ak bon sipò ak yon gwo kominote;
  • li nesesè asire segondè disponiblite nan koutye mesaj la, pou ki li dwe fizikman separe de aplikasyon yo entegre (segondè disponiblite nan aplikasyon ak aplike lojik biznis se pi difisil ak chè asire);
  • koutye a oblije bay "omwen yon fwa" garanti livrezon. Sa a se yon kondisyon obligatwa pou operasyon serye nan otobis entegrasyon an. Pa gen okenn nesesite pou garanti nivo "egzakteman yon fwa": pwosesis biznis yo, kòm yon règ, yo pa sansib a arive repete mesaj oswa evènman, ak nan travay espesyal kote sa a enpòtan, li pi fasil ajoute chèk adisyonèl nan biznis la. lojik pase yo toujou ap sèvi ak garanti byen "chè" ";
  • voye mesaj ak siyal yo dwe patisipe nan yon tranzaksyon jeneral ak chanjman nan eta a nan pwosesis biznis ak done domèn. Opsyon pi pito a ta dwe sèvi ak yon modèl Bwat D' Tranzaksyon, men li pral mande pou yon tab adisyonèl nan baz done a ak yon repete. Nan aplikasyon JEE, sa ka senplifye lè w sèvi ak yon manadjè JTA lokal, men koneksyon an ak koutye chwazi a dwe kapab travay nan XA;
  • moun k ap okipe mesaj ak evènman k ap vini yo dwe travay tou ak yon tranzaksyon ki chanje eta a nan yon pwosesis biznis: si yon tranzaksyon sa yo woule tounen, Lè sa a, resi mesaj la dwe anile;
  • mesaj ki pa t 'kapab delivre akòz erè yo dwe estoke nan yon depo separe D.L.Q. (Dead Letter Queue). Pou rezon sa a, nou te kreye yon mikwosèvis platfòm separe ki estoke mesaj sa yo nan depo li yo, endèks yo pa atribi (pou gwoupman rapid ak rechèch), epi ekspoze yon API pou gade, voye yo nan adrès destinasyon an, ak efase mesaj yo. Administratè sistèm yo ka travay avèk sèvis sa a atravè koòdone entènèt yo;
  • nan paramèt koutye yo, ou bezwen ajiste kantite reta livrezon ak reta ant livrezon yo nan lòd yo diminye chans pou mesaj yo antre nan DLQ (li prèske enposib kalkile paramèt yo pi bon, men ou ka aji anpirik epi ajiste yo pandan operasyon an). );
  • Yo dwe kontwole magazen DLQ la kontinyèlman, epi sistèm siveyans la dwe avèti administratè sistèm yo pou lè mesaj ki pa delivre yo rive, yo ka reponn pi vit posib. Sa ap redwi "zòn ki afekte" yon echèk oswa erè lojik biznis;
  • otobis entegrasyon an dwe ensansib absans tanporè aplikasyon yo: abònman nan yon sijè yo dwe dirab, ak non domèn aplikasyon an dwe inik pou ke pandan aplikasyon an absan, yon lòt moun pa pral eseye trete mesaj li yo soti nan la. keu.

Asire sekirite fil nan lojik biznis

Menm egzanp nan yon pwosesis biznis ka resevwa plizyè mesaj ak evènman nan yon fwa, pwosesis la nan ki pral kòmanse nan paralèl. An menm tan an, pou pwomotè aplikasyon an, tout bagay ta dwe senp epi san danje.

Lojik biznis nan yon pwosesis trete chak evènman ekstèn ki afekte pwosesis biznis sa a endividyèlman. Evènman sa yo ta ka:

  • lanse yon egzanp pwosesis biznis;
  • aksyon itilizatè ki gen rapò ak aktivite nan yon pwosesis biznis;
  • resevwa yon mesaj oswa siyal kote yon egzanp pwosesis biznis abònman;
  • deklanche nan yon revèy mete pa yon egzanp pwosesis biznis;
  • aksyon kontwòl atravè API (pa egzanp, entèripsyon pwosesis).

Chak evènman sa yo ka chanje eta a nan yon egzanp pwosesis biznis: kèk aktivite ka fini ak lòt ka kòmanse, ak valè pwopriyete ki pèsistan ka chanje. Fèmen nenpòt aktivite ka lakòz deklanchman youn oswa plizyè nan aktivite sa yo. Moun sa yo, nan vire, ka sispann ap tann pou lòt evènman oswa, si yo pa bezwen okenn done adisyonèl, ka ranpli nan menm tranzaksyon an. Anvan yo fèmen tranzaksyon an, nouvo eta a nan pwosesis biznis la sove nan baz done a, kote li pral tann pou pwochen evènman an ekstèn rive.

Done pwosesis biznis pèsistan ki estoke nan yon baz done relasyon se yon pwen trè pratik pou senkronize pwosesis si w itilize SELECT FOR UPDATE. Si yon sèl tranzaksyon te jere jwenn eta a nan yon pwosesis biznis nan baz la pou chanje li, Lè sa a, pa gen okenn lòt tranzaksyon an paralèl yo pral kapab jwenn menm eta a pou yon lòt chanjman, epi apre fini an nan premye tranzaksyon an, dezyèm lan se. garanti pou resevwa eta a deja chanje.

Sèvi ak kadna pesimis sou bò DBMS, nou ranpli tout kondisyon ki nesesè yo ASID, epi tou kenbe kapasite nan echèl aplikasyon an ak lojik biznis lè yo ogmante kantite ka kouri.

Sepandan, kadna pesimis menase nou ak enpas, ki vle di ke SELECT FOR UPDATE ta dwe toujou limite a kèk delè rezonab nan ka enpas rive sou kèk ka flagran nan lojik biznis la.

Yon lòt pwoblèm se senkronizasyon nan kòmansman an nan yon pwosesis biznis. Pandan ke pa gen okenn egzanp nan yon pwosesis biznis, pa gen okenn eta nan baz done a, kidonk metòd ki dekri a pa pral travay. Si ou bezwen asire inik nan yon egzanp pwosesis biznis nan yon sijè ki abòde espesifik, Lè sa a, w ap bezwen kèk kalite objè senkronizasyon ki asosye ak klas pwosesis la ak dimansyon ki koresponn lan. Pou rezoud pwoblèm sa a, nou itilize yon mekanis fèmen diferan ki pèmèt nou pran yon kadna sou yon resous abitrè ki espesifye nan yon kle nan fòma URI atravè yon sèvis ekstèn.

Nan egzanp nou yo, pwosesis biznis InitialPlayer la gen yon deklarasyon

uniqueConstraint = UniqueConstraints.singleton

Se poutèt sa, boutèy demi lit la gen mesaj sou pran ak lage seri kle ki koresponn lan. Pa gen mesaj sa yo pou lòt pwosesis biznis: uniqueConstraint pa mete.

Pwoblèm nan pwosesis biznis ak eta ki pèsistan

Pafwa gen yon eta ki pèsistan pa sèlman ede, men tou reyèlman anpeche devlopman.
Pwoblèm yo kòmanse lè yo bezwen fè chanjman nan lojik biznis ak/oswa modèl pwosesis biznis la. Se pa tout chanjman sa yo konpatib ak ansyen eta pwosesis biznis yo. Si gen anpil ka viv nan baz done a, Lè sa a, fè chanjman enkonpatib ka lakòz anpil pwoblèm, ke nou souvan rankontre lè w ap itilize jBPM.

Tou depan de pwofondè chanjman yo, ou ka aji nan de fason:

  1. kreye yon nouvo kalite pwosesis biznis pou yo pa fè chanjman enkonpatib nan ansyen an, epi sèvi ak li olye de ansyen an lè lanse nouvo ka. Ansyen kopi yo ap kontinye travay "tankou anvan";
  2. imigre eta ki pèsistan nan pwosesis biznis lè mete ajou lojik biznis.

Premye fason a pi senp, men li gen limit ak dezavantaj li yo, pou egzanp:

  • repetisyon nan lojik biznis nan anpil modèl pwosesis biznis, ogmante volim nan lojik biznis;
  • Souvan yon tranzisyon imedyat nan nouvo lojik biznis obligatwa (an tèm de travay entegrasyon - prèske toujou);
  • pwomotè a pa konnen nan ki pwen modèl demode yo ka efase.

Nan pratik nou itilize tou de apwòch, men nou pran yon kantite desizyon pou rann lavi nou pi fasil:

  • Nan baz done a, eta ki pèsistan nan yon pwosesis biznis ki estoke nan yon fòm fasil lizib ak fasil trete: nan yon fisèl fòma JSON. Sa a pèmèt migrasyon yo dwe fèt tou de nan aplikasyon an ak deyò. Kòm yon dènye rekou, ou ka korije li manyèlman (sitou itil nan devlopman pandan debogaj);
  • lojik biznis entegrasyon an pa sèvi ak non pwosesis biznis yo, se konsa ke nenpòt ki lè li posib ranplase aplikasyon an nan youn nan pwosesis k ap patisipe yo ak yon nouvo ak yon nouvo non (pa egzanp, "InitialPlayerV2"). Liaison a rive nan mesaj ak non siyal;
  • modèl pwosesis la gen yon nimewo vèsyon, ke nou ogmante si nou fè chanjman enkonpatib nan modèl sa a, epi nimewo sa a sove ansanm ak eta a nan egzanp pwosesis la;
  • se eta a ki pèsistan nan pwosesis la li nan baz done a an premye nan yon modèl objè pratik, ki pwosedi migrasyon an ka travay ak si nimewo a vèsyon modèl chanje;
  • se pwosedi migrasyon an mete akote lojik biznis la epi yo rele "parese" pou chak egzanp nan pwosesis biznis la nan moman restorasyon li soti nan baz done a;
  • si ou bezwen emigre eta a nan tout enstans pwosesis yo byen vit ak synchrone, plis solisyon migrasyon baz done klasik yo itilize, men ou dwe travay ak JSON.

Ou bezwen yon lòt kad pou pwosesis biznis?

Solisyon yo dekri nan atik la pèmèt nou siyifikativman senplifye lavi nou, elaji seri pwoblèm ki rezoud nan nivo devlopman aplikasyon an, epi fè lide separe lojik biznis nan mikwosèvis pi atire. Pou reyalize sa a, yo te fè anpil travay, yo te kreye yon fondasyon trè "lejè" pou pwosesis biznis yo, ansanm ak konpozan sèvis pou rezoud pwoblèm yo idantifye nan kontèks yon pakèt pwoblèm aplikasyon. Nou gen yon dezi pataje rezilta sa yo epi fè devlopman nan eleman komen aksè louvri anba yon lisans gratis. Sa a pral mande pou kèk efò ak tan. Konprann demann lan pou solisyon sa yo ta ka yon ankourajman adisyonèl pou nou. Nan atik yo pwopoze a, yo peye anpil atansyon sou kapasite fondasyon an tèt li, men kèk nan yo vizib nan egzanp yo prezante. Si nou pibliye kad nou an, yon atik apa pral konsakre pou li. Antretan, nou ta rekonesan si ou kite yon ti fidbak lè w reponn kesyon an:

Se sèlman itilizatè ki anrejistre ki ka patisipe nan sondaj la. Enskri, tanpri.

Ou bezwen yon lòt kad pou pwosesis biznis?

  • 18,8%Wi, depi lontan mwen tap chèche yon bagay konsa

  • 12,5%Mwen enterese aprann plis sou aplikasyon w lan, li ta ka itil2

  • 6,2%Nou itilize youn nan kad ki deja egziste yo, men nou panse pou ranplase1

  • 18,8%Nou itilize youn nan kad ki deja egziste yo, tout bagay anfòm3

  • 18,8%nou jere san yon kad3

  • 25,0%ekri pa w la4

16 itilizatè yo te vote. 7 itilizatè te absteni.

Sous: www.habr.com

Add nouvo kòmantè