BPE

MODEL

You can use Camunda Modeler of bpmn.io with BPE:

SESSION

Transactional persistent (rocksdb) business processing with multi-threading executioin, hierarchical traces and BPMN 2.0 XML support out of the box.

iex(1)> {_,p} = :bpe.start :bpe_xml.def, [] {:ok, "77012724426000"} 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, 'epilog'} iex(7)> :bpe.next p {:complete, 'finish'} iex(8)> :bpe.next p :Final
How the process is stored in KVS
iex(10)> :kvs.all :writer [ {:writer, '/bpe/proc', 1, [], [], []}, {:writer, '/bpe/flow/77012724426000', 1, [], [], []}, {:writer, '/bpe/hist/77012724426000', 1, [], [], []} ]
The hierarchical process trace of flows but not tasks:
iex(11)> :bpe.hist p [ {:hist, {:step, 7, '77012724426000'}, :feed, [], [], [], [], {:sequenceFlow, 'x7', [], 'epilog', 'finish'}, [], {:ts, {{2019, 10, 11}, {4, 3, 7}}}}, {:hist, {:step, 6, '77012724426000'}, :feed, [], [], [], [], {:sequenceFlow, 'x6', [], 'join', 'epilog'}, [], {:ts, {{2019, 10, 11}, {4, 3, 6}}}}, {:hist, {:step, 5, '77012724426000'}, :feed, [], [], [], [], {:sequenceFlow, 'x5', [], 'right', 'join'}, [], {:ts, {{2019, 10, 11}, {4, 3, 6}}}}, {:hist, {:step, 4, '77012724426000'}, :feed, [], [], [], [], {:sequenceFlow, 'x4', [], 'left', 'join'}, [], {:ts, {{2019, 10, 11}, {4, 3, 6}}}}, {:hist, {:step, 3, '77012724426000'}, :feed, [], [], [], [], {:sequenceFlow, 'x3', [], 'either', 'right'}, [], {:ts, {{2019, 10, 11}, {4, 3, 5}}}}, {:hist, {:step, 2, '77012724426000'}, :feed, [], [], [], [], {:sequenceFlow, 'x2', [], 'either', 'left'}, [], {:ts, {{2019, 10, 11}, {4, 3, 5}}}}, {:hist, {:step, 1, '77012724426000'}, :feed, [], [], [], [], {:sequenceFlow, 'x1', [], 'start', 'either'}, [], {:ts, {{2019, 10, 11}, {4, 3, 4}}}}, {:hist, {:step, 0, '77012724426000'}, :feed, [], [], [], [], :Created, [], {:ts, {{2019, 10, 11}, {4, 2, 25}}}} ]
The history of scheduler state of execution threads:
> :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, []} ]

BPMN SPEC

This schema covers 80% of all workflows and provides only 20% of standard coverage. We call it Lightweight BPMN or BPE.

Lightweight BPMN
-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{} }). -record(gateway, { ?TASK, type= parallel :: gate(), filler=[] :: [] }). -record(messageEvent, { ?EVENT }). -record(boundaryEvent, { ?EVENT, ?CYCLIC }). -record(timeoutEvent, { ?EVENT, ?CYCLIC }). -record(timeout, { spec= [] :: term() }). -record(sequenceFlow, { name=[] :: term(), condition=[] :: term(), source=[] :: [] | atom(), target=[] :: [] | atom() | list(atom()) }). -type events() :: #messageEvent{} | #boundaryEvent{} | #timeoutEvent{}. -type procId() :: [] | integer() | {atom(),any()}. -type gate() :: exclusive | parallel | inclusive | complex | event. -type tasks() :: #task{} | #serviceTask{} | #userTask{} | #receiveTask{} | #beginEvent{} | #endEvent{}.

BPE API

BPE API
-record(ts, { time= [] :: term() }). -record(step, { id = 0 :: integer(), proc = "" :: list() }). -record(sched, { id = [] :: [] | #step{}, pointer = -1 :: integer(), state = [] :: list(#sequenceFlow{}) }). -record(hist, { id = [] :: [] | #step{}, name=[] :: [] | binary(), task=[] :: [] | atom(), docs=[] :: list(tuple()), time=[] :: [] | #ts{} }). -record(process, { id = [] :: procId(), name=[] :: [] | binary() | string() | atom(), feeds=[] :: list(), roles=[] :: list(), tasks=[] :: list(tasks()), events=[] :: list(events()), flows = [] :: list(#sequenceFlow{}), rules = [] :: [] | term(), docs = [] :: list(tuple()), options = [] :: term(), task = 'Created' :: [] | atom(), timer = [] :: [] | reference(), notifications=[] :: [] | term(), result = [] :: [] | binary(), started = [] :: [] | #ts{}, beginEvent = [] :: [] | atom(), endEvent = [] :: [] | atom()}). -record(subProcess, { name=[] :: [] | atom(), diagram= #process{} :: #process{} }).

BANK SAMPLE

IBAN account transactions as a process:
-module(bpe_account). -include("bpe.hrl"). -compile(export_all). action(_,P) -> {reply,P}. def() -> #process { name = 'IBAN Account', flows = [ #sequenceFlow{name='1', source='Created', target='Init'}, #sequenceFlow{name='2', source='Init', target='Upload'}, #sequenceFlow{name='3', source='Upload', target='Payment'}, #sequenceFlow{name='4', source='Payment', target='Signatory'}, #sequenceFlow{name='5', source='Payment', target='Process'}, #sequenceFlow{name='6', source='Process', target='Process'}, #sequenceFlow{name='7', source='Process', target='Final'}, #sequenceFlow{name='8', source='Signatory', target='Process'}, #sequenceFlow{name='9', source='Signatory', target='Final'} ], tasks = [ #beginEvent { name='Created', module = bpe_account }, #userTask { name='Init', module = bpe_account }, #userTask { name='Upload', module = bpe_account }, #userTask { name='Signatory', module = bpe_account }, #serviceTask { name='Payment', module = bpe_account }, #serviceTask { name='Process', module = bpe_account }, #endEvent { name='Final', module = bpe_account } ], beginEvent = 'Created', endEvent = 'Final', events = [#messageEvent { name='PaymentReceived'}, #boundaryEvent{ name='*', timeout=#timeout{spec={0,{10,0,10}}}}]}.

PRESENCE

Companies that use BPE:



CONTRIBUTORS