bpmn-js Token Simulation Internals

An update on recent improvements.

Nico Rehwaldt

About Me

  • Software developer at Camunda
  • bpmn.io creator and project lead
  • @nikku on GitHub
2

Agenda

1️⃣ Where we started

2️⃣ What we accomplished

3

1️⃣ Where we Started

4

Token simulation presentation

5

Camunda Community Summit

  • Presentation received positive feedback
  • Also highlighted some issues
6

It is a fun project to hack upon.

7

➡️ Let's go!

8

Goals

  • Gain a deep understanding of token-simulation
  • Improve maintainability ➡️ Make contributions possible
  • Make it work (BPMN 2.0 compliant) and powerful (complex BPMN elements)
9

2️⃣ What we Accomplished

10

Token simulation overview

11

In a Nutshell

  • A standalone simulator
  • A solid execution model
  • An improved testing story
  • Just add animations
  • General housekeeping
12

A Standalone Simulator

🟡 Single instance process-engine, scattered across the whole code base, i.e. context pad handlers and simulation behavior.

🟢 Dedicated, multi-instance simulator with own state management. Driven via API, hooked into via events.

🟢 Executes signals, escalation, message flows and most other complex BPMN behaviors.

13

A Solid Execution Model

🟢 Scopes represent activities

🟢 Behaviors implement element specific scope enter, exit and signal (user trigger) actions

14

Scope in action

15

🟢 Drive the Simulation

const processElement = elementRegistry.get('Process');
const startEventElement = elementRegistry.get('StartEvent');

// start instance of <Process>
simulator.signal({
  element: processElement,
  startEvent: startEventElement
});
16

🟢 Query Active Scopes

const processElement = elementRegistry.get('Process');

// active instances in <Process>
const runningScopes = simulator.findScopes({
  element: processElement
});
17

🟢 Register a Behavior

function TaskBehavior(simulator) {
  simulator.registerBehavior('bpmn:Task', this);
}
18

🟢 Exit a Task

TaskBehavior.prototype.exit = function(context) {
  context.element.outgoing.filter(isSequenceFlow).map(flow => {
    simulator.enter({
      element: flow,
      parentScope: context.scope.parent
    });
  });
};
19

An Improved Testing Story

🟡 UI integration testing only.

🟢 Dedicated tests against the simulator API.

🟢 UI tests as a layer on top.

20

🟢 Dedicated Simulator Tests

verify('simple', () => {

  // when
  signal({
    element: element('Process_1')
  });

  // then
  expectTrace(...);
});
21

🟢 UI-based Integration Tests

it('should execute happy path', async function() {

  // when
  triggerElement('StartEvent_1');

  await scopeDestroyed();

  // then
  expectHistory(...);
});
22

🟢 Test Cover All Things!

bpmn-js-token-simulation test coverage diagram

23

🟢 Just Add Animation

AnimatedSequenceFlowBehavior.prototype.enter = function(context) {

  const {
    element,
    scope
  } = context;

  this._animation.animate(element, scope, () => {
    SequenceFlowBehavior.prototype.enter.call(this, context);
  });
};
24

General Housekeeping

🟢 Migrate to ES modules

🟢 Migrate to GitHub actions

🟢 Remove SVG.js in favor of own animation core

25

bpmn-js-token-simulation test coverage diagram

26
27

Even more could be done

  • Visual token trace
  • Life- / deadlock detection
  • Transactions
  • ...
28
29

Thank you. Questions?

30

Contribute to Token Simulation

You like the token simulation tool? Consider contributing on Github and help us to make it even better ❤️.

31
32