• Stars
    star
    265
  • Rank 154,553 (Top 4 %)
  • Language
    Erlang
  • License
    Other
  • Created over 10 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ’  BPE: BPMN Process Engine ISO 19510

BPE: Business Process Engine

Actions Status Hex pm

Overview

BPE is a Business Process Engine that brings BPMN to Erlang and Erlang to Enterprises. It provides infrastructure for Workflow Definitions, Process Orchestration, Rule Based Production Systems and Distributed Storage.


 iex(1)> {_,p} = :bpe.start :bpe_xml.def, []
 {:ok, '76900759556000'}
 iex(2)> :bpe.next p
 {:complete, 'either'}
 iex(3)> :bpe.next p
 {:complete, 'left'}
 iex(4)> :bpe.next p
 {:complete, 'right'}
 iex(5)> :bpe.next p
 {:complete, 'join'}
 iex(6)> :bpe.next p
 {:complete, 'join'}
 iex(7)> :bpe.next p
 {:complete, 'epilog'}
 iex(8)> :bpe.next p
 {:complete, 'finish'}
 iex(9)> :bpe.next p
 :Final
> :kvs.all '/bpe/flow/77012724426000'
 [
   {:sched, {:step, 0, '77012724426000'}, 1, ['x1']},
   {:sched, {:step, 1, '77012724426000'}, 1, ['x2', 'x3']},
   {:sched, {:step, 2, '77012724426000'}, 2, ['x4', 'x3']},
   {:sched, {:step, 3, '77012724426000'}, 1, ['x4', 'x5']},
   {:sched, {:step, 4, '77012724426000'}, 1, ['x5']},
   {:sched, {:step, 5, '77012724426000'}, 1, ['x6']},
   {:sched, {:step, 6, '77012724426000'}, 1, ['x7']},
   {:sched, {:step, 7, '77012724426000'}, 1, []}
 ]

Processes

Processes are main entities of BPE, they map one-to-one to Erlang processes. Basically, BPE process is an algorithm or function, that is executed entirely in the context of Erlang process. The arguments for such algorithms are: values from infinite streams (KVS chains); values from Erlang messages being sent to BPE process.

-record(step,  { id = 0 :: integer(), proc = "" :: list() }).

-record(role,  { id = [] :: list(), name :: binary(), tasks = [] :: term() }).

-record(sched, { id = [] :: [] | #step{},
                 prev=[] :: [] | integer(),
                 next=[] :: [] | integer(),
                 pointer = -1 :: integer(),
                 state = [] :: list(list()) }).
                 
-record(hist,         { id = [] :: [] | #step{},
                        prev=[] :: [] | integer(),
                        next=[] :: [] | integer(),
                        name=[] :: [] | binary() | list(),
                        task=[] :: [] | atom() | list() | #sequenceFlow{} | condition(),
                        docs=[] :: list(tuple()),
                        time=[] :: [] | #ts{} }).

-record(process,      { id = [] :: procId(),
                        prev=[] :: [] | integer(),
                        next=[] :: [] | integer(),
                        name=[] :: [] | binary() | string() | atom(),
                        feeds=[] :: list(),
                        roles      = [] :: term(),
                        tasks      = [] :: list(tasks()),
                        events     = [] :: list(events()),
                        flows      = [] :: list(#sequenceFlow{}),
                        docs       = [] :: list(tuple()),
                        options    = [] :: term(),
                        module     = ?DEFAULT_MODULE :: [] | atom(),
                        xml        = [] :: list(),
                        timer      = [] :: [] | reference(),
                        notifications=[] :: [] | term(),
                        result     = [] :: [] | binary(),
                        started    = [] :: [] | #ts{},
                        beginEvent = [] :: list() | atom(),
                        endEvent   = [] :: list() | atom() }).

During execution of the process, all steps are being written to the persistent storage, by which execution logic is restorable and reproducible. The process definition is actually diagram or graph where points represented by task and edges by sequenceFlow.

Tasks and Flows

The step itself is represented as task (point). The transition between steps is represented as sequenceFlow (edge).

-define(TASK,           id=[] :: list(),
                        name=[] :: list() | binary(),
                        in=[] :: list(list()),
                        out=[] :: list(list()),
                        prompt=[] :: list(tuple()),
                        roles=[] :: list(atom()),
                        etc=[] :: list({term(),term()}) ).

-record(beginEvent ,  { ?TASK }).
-record(endEvent,     { ?TASK }).
-record(task,         { ?TASK }).
-record(userTask,     { ?TASK }).
-record(serviceTask,  { ?TASK }).
-record(receiveTask,  { ?TASK, reader=[] :: #reader{} }).
-record(sendTask,     { ?TASK, writer=[] :: #writer{} }).

The history record of process execution is represented as hist and captures the sequenceFlow information.

-type condition() :: {compare,BpeDocParam :: 
                         { atom(),
                           term()},
                           Field :: integer(),
                           ConstCheckAgainst :: term()
                         }
                   | {service,atom()}.

-record(sequenceFlow, { id=[] :: list(),
                        name=[] :: list() | binary(),
                        condition=[] :: [] | condition() | binary(),
                        source=[] :: list(),
                        target=[] :: list(integer()) | list(list()) }).

Events

While Tasks are deterministic, where you're getting a new task from previous one, the Events are non-deterministic, where you could get a new task by external event from the system to the process.

-define(EVENT,          id=[] :: list() | atom(),
                        name=[] :: list() | binary(),
                        prompt=[] :: list(tuple()),
                        etc=[] :: list({term(),term()}),
                        payload=[] :: [] | binary(),
                        timeout=[] :: [] | #timeout{} ).

-define(CYCLIC,         timeDate=[] :: [] | binary(),
                        timeDuration=[] :: [] | binary(),
                        timeCycle=[] :: [] | binary() ).

-record(messageEvent, { ?EVENT }).
-record(messageBeginEvent, { ?EVENT }).
-record(boundaryEvent,{ ?EVENT, ?CYCLIC }).
-record(timeoutEvent, { ?EVENT, ?CYCLIC }).

Gateways

Gateways represent multiplexors and demultiplexors which cause non-linear trace and multiple current states as leaves of execution graph.

-type gate()   :: exclusive | parallel | inclusive | complex | event.

-record(gateway,      { ?TASK, type= parallel :: gate() }).

Full set of BPMN 2.0 fields could be obtained at http://www.omg.org/spec/BPMN/2.0, page 3-7.

Sample Session

(bpe@127.0.0.1)1> rr(bpe).
[beginEvent,container,endEvent,history,id_seq,iterator,
 messageEvent,process,sequenceFlow,serviceTask,task,userTask]
(bpe@127.0.0.1)2> bpe:start(spawnproc:def(),[]).
bpe_proc:Process 39 spawned <0.12399.0>
{ok,<0.12399.0>}
(bpe@127.0.0.1)3> bpe:complete(39).
(bpe@127.0.0.1)4> bpe:complete(39).
(bpe@127.0.0.1)5> bpe:complete(39).
(bpe@127.0.0.1)5> bpe:hist(39).
[#history{id = 28,version = undefined,container = feed,
          feed_id = {history,39},
          prev = 27,next = undefined,feeds = [],guard = true,
          etc = undefined,name = "Order11",
          task = {task,"end"}},
 #history{id = 27,version = undefined,container = feed,
          feed_id = {history,39},
          prev = 26,next = 28,feeds = [],guard = true,etc = undefined,
          name = "Order11",
          task = {task,"end2"}},
 #history{id = 26,version = undefined,container = feed,
          feed_id = {history,39},
          prev = undefined,next = 27,feeds = [],guard = true,
          etc = undefined,name = "Order11",
          task = {task,"begin"}}]

Process Instances

Instantiation of process means creating persistent context of document flow.

load(ProcName)
start(Proc,Docs)
amend(Proc,Docs)
complete(Proc)
history(ProcId)
task(Name,Proc)
doc(Name,Proc)
events(Proc)
tasks(Proc)

Using 'tasks' API you can fetch current documents attached to the given process at particular stage. Using 'amend' API you can upload or change document at current stage. 'push' API moves current stage documents further by workflow.

Let us see how we could create initial 'Wire Transfer' transaction:

> rr(bpe).
[ beginEvent,boundaryEvent,container,endEvent,history,id_seq,
  interval,iterator,kvs,log,messageEvent,operation,process,
  receiveTask,sequenceFlow,serviceTask,task,timeoutEvent,userTask ]

> rr(kvs).
[column,config,container,id_seq,interval,iterator,kvs,log,
 operation,query,schema,table,user,user2]

> Proc = bpe:load(39).

> bpe:tasks(Proc).
  [#userTask{name = 'Init',roles = [], module = spawnproc},
   #userTask{name = 'Signatory',roles = [], module = spawnproc},
   #serviceTask{name = 'Payment',roles = [], module = spawnproc},
   #serviceTask{name = 'Process',roles = [], module = spawnproc},
   #endEvent{name = 'Final',module = []}]

> bpe:docs(Proc).
  []

> bpe:amend(39,[{'WireTransfer',#user{id=1},#user{id=2}}]).

> bpe:docs(bpe:load(39)).

Credits

  • Maxim Sokhatsky
  • Oleksandr Naumov
  • Ivan Kulyk

OM A HUM

More Repositories

1

n2o

β­• N2O: Distributed WebSocket Application Server ISO 20922
Erlang
1,340
star
2

shen

πŸ‰ SHEN: Erlang JavaScript Compiler
Erlang
234
star
3

kvs

πŸ’Ώ KVS: NVMe Key-Value Store
Erlang
177
star
4

mad

⚑ MAD: Managing Application Dependencies LING/UNIX
Erlang
173
star
5

rest

β˜• REST: RFC-2616 Framework
Erlang
83
star
6

cr

πŸ’  CR: Chain Replication Database for KVS
Erlang
57
star
7

ldap

🌐 LDAP: Directory Server. ITU/IETF: 2849, 3296, 3671-3673, 3866, 4510-4518, 4522, 4525, 4526, 4929, 5480, X.519.
Erlang
53
star
8

nitro

πŸ”₯ NITRO: Nitrogen Web Framework RFC 6455
Erlang
53
star
9

form

🧾 FORM: Business X-Forms
Erlang
39
star
10

exe

πŸ–₯️ EXE: Shell Exec
Erlang
37
star
11

mail

βœ‰οΈ MAIL: Message Handling Service. ISO/IEC: 10021; ITU/IETF: X.400β€”X.403, X.407β€”X.408, X.411β€”X.413, X.419β€”X.420.
Erlang
25
star
12

rpc

☎️ RPC: Type Driven Parser Generator
Erlang
18
star
13

ca

πŸ›‘οΈ CA: Certificate Authority. Π”Π‘Π’Π£: 4145. ITU/IETF: 3279, 5755, X.501, X.509, X.511, X.520.
Erlang
17
star
14

n2o.dev

🌐 N2O.DEV: Open Source Enterprise Frameworks
CSS
13
star
15

sample

πŸ’§ SAMPLE: WebSocket Sample Application
Erlang
9
star
16

rt

β˜€ RT: Erlang Runtime Library
Erlang
8
star
17

synrc.com

🌐 SYNRC: Commercial Support
HTML
7
star
18

base

β˜€ BASE: Erlang Base Library
Elixir
6
star
19

chat

πŸ’¬ CHAT: Instant Messenger. ISO/IEC: 20922; ITU/IETF: 3394, 3565, 5280, 5480, 5652, 5755 8551, X.509, CMS, PKCS-10, PCKS-7, OCSP, LDAP, DNS; ANSI: X9-42, X9-62, X25519, X488; NIST: SECP384r1.
Erlang
6
star
20

svg

πŸš€ SVG: Vector HTML5 DSL
Erlang
5
star
21

review

πŸ’§ REVIEW: MQTT Sample Application
Erlang
5
star
22

ns

πŸ”’ NS: Name Server IETF 1034, 1035, 1101, 2065, 2535, 2539, 4033-4035 4398, 6944
Erlang
5
star
23

mq

πŸ“Ÿ MQ: MQTT Server ISO 20922
HTML
4
star
24

storybook

πŸ“’ NITRO: Storybook
Erlang
1
star
25

k8s.n2o.dev

🌐 N2O.K8S: SYNRC Cloud Platform
1
star