Skip to content

Commit 1b39f6b

Browse files
committed
disallow recovering or resuming a running engine
minor update of moddle-context-serializer
1 parent 1b28cfd commit 1b39f6b

File tree

7 files changed

+61
-10
lines changed

7 files changed

+61
-10
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## [25.0.0] - 2025-03-17
4+
5+
It has been possible to recover a running engine. The execution was overwritten and all references to timers etc was lost. This stops with this version. Either stop the the execution or wait for it to end if the engine should be re-used. It is highly recommended to initiate a new Engine when recovering from state.
6+
7+
### Breaking
8+
9+
- Disallow a running engine to be recovered and resumed. Recommended is to recover and resume a new Engine instance with state or stop the instance before recovering.
10+
311
## [24.0.1] - 2025-03-14
412

513
- fix recover engine with options not keeping scripts and logger from when initiated

docs/API.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- version -->
22

3-
# 24.0.0 API Reference
3+
# 25.0.0 API Reference
44

55
<!-- versionstop -->
66

@@ -508,6 +508,8 @@ engine.execute({
508508
509509
Recover engine from state.
510510
511+
> NB! Will throw an error if the engine is running.
512+
511513
Arguments:
512514
513515
- `state`: engine state
@@ -524,6 +526,8 @@ const engine = new Engine().recover(state);
524526
525527
Resume execution function with previously saved engine state.
526528
529+
> NB! Attempting to resume a running engine returns error in callback or throws if callback is not passed.
530+
527531
Arguments:
528532
529533
- `options`: optional resume options object

lib/index.cjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,7 @@ Engine.prototype.stop = function stop() {
281281

282282
Engine.prototype.recover = function recover(savedState, recoverOptions) {
283283
if (this[kExecution]?.isRunning) {
284-
this.logger.error('recover during running execution will be deprecated next major version');
285-
this.logger.debug(`<${this.name}> stopping current running execution`);
286-
this[kExecution].stop();
284+
throw new Error('cannot recover a running engine');
287285
}
288286

289287
if (!savedState) return this;
@@ -338,6 +336,10 @@ Engine.prototype.resume = async function resume(...args) {
338336
throw err;
339337
}
340338
execution = this[kExecution] = new Execution(this, definitions, this.options);
339+
} else if (execution.isRunning) {
340+
const err = new Error('cannot resume a running engine');
341+
if (callback) return callback(err);
342+
throw err;
341343
}
342344

343345
return execution._resume(resumeOptions, callback);

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "bpmn-engine",
33
"description": "BPMN 2.0 execution engine. Open source javascript workflow engine.",
4-
"version": "24.0.1",
4+
"version": "25.0.0",
55
"type": "module",
66
"module": "./src/index.js",
77
"main": "./lib/index.cjs",
@@ -72,7 +72,7 @@
7272
"bpmn-elements": "^17.0.0",
7373
"bpmn-moddle": "^9.0.1",
7474
"debug": "^4.3.7",
75-
"moddle-context-serializer": "^4.2.1"
75+
"moddle-context-serializer": "^4.3.0"
7676
},
7777
"peerDependencies": {
7878
"smqp": ">=9"

src/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,7 @@ Engine.prototype.stop = function stop() {
135135

136136
Engine.prototype.recover = function recover(savedState, recoverOptions) {
137137
if (this[kExecution]?.isRunning) {
138-
this.logger.error('recover during running execution will be deprecated next major version');
139-
this.logger.debug(`<${this.name}> stopping current running execution`);
140-
this[kExecution].stop();
138+
throw new Error('cannot recover a running engine');
141139
}
142140

143141
if (!savedState) return this;
@@ -192,6 +190,10 @@ Engine.prototype.resume = async function resume(...args) {
192190
throw err;
193191
}
194192
execution = this[kExecution] = new Execution(this, definitions, this.options);
193+
} else if (execution.isRunning) {
194+
const err = new Error('cannot resume a running engine');
195+
if (callback) return callback(err);
196+
throw err;
195197
}
196198

197199
return execution._resume(resumeOptions, callback);

test/feature/issues/issue-199-feature.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ Feature('issue 199 - Issue with Script Tasks After State Recovery in bpmn-engine
8686
expect(execution.state).to.equal('running');
8787
});
8888

89+
Given('execution is stopped', () => {
90+
return execution.stop();
91+
});
92+
8993
When('same instance is recovered with options', () => {
9094
engine.recover(state, {
9195
services: {

test/feature/resume-feature.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,39 @@ Feature('Resume execution', () => {
329329
expect(execution1.activityStatus).to.equal('timer');
330330
});
331331

332+
And('attempting to recover a running engine instance throws', () => {
333+
expect(() => {
334+
engine.recover(execution1.getState(), {
335+
settings: {
336+
mySetting: 1,
337+
},
338+
});
339+
}).to.throw(/running/);
340+
});
341+
342+
And('attempting to resume a running engine instance throws', async () => {
343+
try {
344+
await engine.resume();
345+
} catch (err) {
346+
// eslint-disable-next-line no-var
347+
var error = err;
348+
}
349+
expect(error).to.match(/running/);
350+
});
351+
352+
And('attempting to resume a running engine instance with callback returns error in callback', (done) => {
353+
engine.resume((err) => {
354+
expect(err).to.match(/running/);
355+
done();
356+
});
357+
});
358+
359+
Given('execution is stopped', () => {
360+
return execution1.stop();
361+
});
362+
332363
let execution2;
333-
When('same instance is recovered options and resumed', async () => {
364+
When('same instance is recovered with options and resumed', async () => {
334365
engine.recover(execution1.getState(), {
335366
settings: {
336367
mySetting: 1,

0 commit comments

Comments
 (0)