Skip to content

Commit

Permalink
process historyTimeToLive negative and zero return P0D duration
Browse files Browse the repository at this point in the history
  • Loading branch information
paed01 committed May 25, 2024
1 parent 54ada99 commit 5d6e06d
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 83 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

# unreleased

# 8.1.0

- process history time to live negative and zero days both result in time duration `P0D`

# 8.0.3

- add iso8601 to OnifyTimerEventDefinition supports list to avoid confusion
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onify/flow-extensions",
"version": "8.0.3",
"version": "8.1.0",
"description": "Onify Flow extensions",
"type": "module",
"module": "src/index.js",
Expand All @@ -20,13 +20,13 @@
}
},
"scripts": {
"test": "mocha -R dot",
"test": "mocha",
"posttest": "npm run lint && npm run dist && texample",
"lint": "eslint . --cache && prettier . --check --cache",
"prepare": "npm run dist",
"dist": "babel src -d dist && babel test/helpers/FlowScripts.js -d dist",
"test:lcov": "c8 -r lcov mocha && npm run lint",
"cov:html": "c8 mocha -R dot && c8 report --reporter html"
"cov:html": "c8 mocha && c8 report --reporter html"
},
"keywords": [
"onify",
Expand Down
5 changes: 3 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ function getHistoryTimeToLiveTimer(behaviour) {
const { id, $type: type, historyTimeToLive } = behaviour;

let value = historyTimeToLive;
if (/^\d+$/.test(historyTimeToLive)) {
value = `P${historyTimeToLive}D`;
let days;
if (!isNaN((days = Number(value)))) {
value = `P${days > 0 ? days : 0}D`;
}
return {
id: `${type}/${id}:historyTimeToLive`,
Expand Down
163 changes: 163 additions & 0 deletions test/features/process-history-ttl-feature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import { parseInterval } from '@0dep/piso';
import testHelpers from '../helpers/testHelpers.js';

Feature('Process history ttl', () => {
Scenario('Flow with process history time to live as number of days', () => {
let source, flow;
Given('a source matching scenario', () => {
source = `<?xml version="1.0" encoding="UTF-8"?>
<definitions id="def_0" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
targetNamespace="http://bpmn.io/schema/bpmn">
<process id="my-process" isExecutable="true" camunda:historyTimeToLive="180">
<userTask id="task" />
</process>
</definitions>`;
});

let serializable;
When('parsed with extend function', async () => {
serializable = await testHelpers.parseOnifyFlow(source);
});

Then('history ttl timer is registered as duration', () => {
expect(serializable.elements.timers[0]).to.deep.equal({
name: 'my-process:historyTimeToLive',
parent: {
id: 'my-process',
type: 'bpmn:Process',
},
timer: {
id: 'bpmn:Process/my-process:historyTimeToLive',
timerType: 'timeDuration',
type: 'historyTimeToLive',
value: 'P180D',
},
});
});

let started, wait;
When('started', async () => {
flow = await testHelpers.getOnifyFlow(source);
started = flow.waitFor('process.start');
wait = flow.waitFor('wait');
flow.run();
});

let historyTtl;
Then('process environment has historyTimeToLive', async () => {
const bp = await started;
expect(bp.environment.variables).to.have.property('historyTimeToLive', 'P180D');
historyTtl = bp.environment.variables.historyTimeToLive;
});

And('it is parsable as ISO8601 duration', () => {
expect(parseInterval(historyTtl).duration.result.D).to.equal(180);
});

let processEnd, state;
When('flow is stopped and resumed', async () => {
await flow.stop();

state = await flow.getState();

processEnd = flow.waitFor('process.end');
return flow.resume();
});

And('task is signaled', async () => {
await wait;
flow.signal({ id: 'task' });
});

Then('process run completes', async () => {
const ended = await processEnd;
expect(ended.environment.variables).to.have.property('historyTimeToLive', historyTtl);
});

When('flow is recovered and resumed from stopped state', async () => {
flow = await testHelpers.recoverOnifyFlow(source, state);
processEnd = flow.waitFor('process.end');
return flow.resume();
});

And('task is signaled', () => {
flow.signal({ id: 'task' });
});

Then('process run completes', async () => {
const ended = await processEnd;
expect(ended.environment.variables).to.have.property('historyTimeToLive', historyTtl);
});
});

Scenario('Flow with process history time to live as negative number of days', () => {
let source;
Given('a source matching scenario', () => {
source = `<?xml version="1.0" encoding="UTF-8"?>
<definitions id="def_0" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
targetNamespace="http://bpmn.io/schema/bpmn">
<process id="my-process" isExecutable="true" camunda:historyTimeToLive="-1">
<userTask id="task" />
</process>
</definitions>`;
});

let serializable;
When('parsed with extend function', async () => {
serializable = await testHelpers.parseOnifyFlow(source);
});

Then('history ttl timer is registered as 0 days', () => {
expect(serializable.elements.timers[0]).to.deep.equal({
name: 'my-process:historyTimeToLive',
parent: {
id: 'my-process',
type: 'bpmn:Process',
},
timer: {
id: 'bpmn:Process/my-process:historyTimeToLive',
timerType: 'timeDuration',
type: 'historyTimeToLive',
value: 'P0D',
},
});
});
});

Scenario('Flow with process history time to live as 0', () => {
let source;
Given('a source matching scenario', () => {
source = `<?xml version="1.0" encoding="UTF-8"?>
<definitions id="def_0" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
targetNamespace="http://bpmn.io/schema/bpmn">
<process id="my-process" isExecutable="true" camunda:historyTimeToLive="0">
<userTask id="task" />
</process>
</definitions>`;
});

let serializable;
When('parsed with extend function', async () => {
serializable = await testHelpers.parseOnifyFlow(source);
});

Then('history ttl timer is registered as 0 days', () => {
expect(serializable.elements.timers[0]).to.deep.equal({
name: 'my-process:historyTimeToLive',
parent: {
id: 'my-process',
type: 'bpmn:Process',
},
timer: {
id: 'bpmn:Process/my-process:historyTimeToLive',
timerType: 'timeDuration',
type: 'historyTimeToLive',
value: 'P0D',
},
});
});
});
});
73 changes: 0 additions & 73 deletions test/features/process-history-ttl-feaure.js

This file was deleted.

19 changes: 14 additions & 5 deletions test/helpers/testHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default {
Logger,
recoverOnifyFlow,
getEngine,
parseOnifyFlow,
};

function moddleContext(source, options) {
Expand All @@ -30,19 +31,27 @@ function moddleContext(source, options) {
* Get Definition as Onify flow with extensions
* @param {string | Buffer} source BPMN source
* @param {import('bpmn-elements').EnvironmentOptions} options Definition options
* @returns {Promise<import('bpmn-elements').Definition>}
*/
async function getOnifyFlow(source, options = {}) {
const { types, ...environmentOptions } = options;
const serialized = await parseOnifyFlow(source, { types });

return new Elements.Definition(new Elements.Context(serialized), getFlowOptions(serialized.name || serialized.id, environmentOptions));
}

/**
* Parse source Onify flow with extensions
* @param {string | Buffer} source BPMN source
* @param {import('bpmn-elements').EnvironmentOptions} options Definition options
*/
async function parseOnifyFlow(source, options = {}) {
const moddle = await moddleContext(source, await getModdleExtensions());
if (moddle.warnings?.length) {
const logger = Logger('bpmn-moddle');
for (const w of moddle.warnings) logger.warn(w);
}

const { types, ...environmentOptions } = options || {};

const serialized = Serializer(moddle, TypeResolver({ ...Elements, TimerEventDefinition, ...types }), extendFn);
return new Elements.Definition(new Elements.Context(serialized), getFlowOptions(serialized.name || serialized.id, environmentOptions));
return Serializer(moddle, TypeResolver({ ...Elements, TimerEventDefinition, ...options.types }), extendFn);
}

/**
Expand Down

0 comments on commit 5d6e06d

Please sign in to comment.