Skip to content

Commit

Permalink
throw on invalid timer type value
Browse files Browse the repository at this point in the history
  • Loading branch information
paed01 committed Apr 27, 2024
1 parent eb2446c commit 79d7324
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 211 deletions.
8 changes: 5 additions & 3 deletions dist/activity/Activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ Object.defineProperties(Activity.prototype, {
}
});
Activity.prototype.activate = function activate() {
if (this[kActivated]) return;
this[kActivated] = true;
this.addInboundListeners();
return this._consumeInbound();
Expand Down Expand Up @@ -892,8 +893,7 @@ Activity.prototype._publishEvent = function publishEvent(state, content, propert
}), {
...properties,
type: state,
mandatory: state === 'error',
persistent: 'persistent' in properties ? properties.persistent : state !== 'stop'
mandatory: state === 'error'
});
};
Activity.prototype._onStop = function onStop(message) {
Expand All @@ -908,7 +908,9 @@ Activity.prototype._onStop = function onStop(message) {
broker.cancel('_format-consumer');
if (this.extensions) this.extensions.deactivate((0, _messageHelper.cloneMessage)(message));
if (running) {
this._publishEvent('stop', this._createMessage());
this._publishEvent('stop', this._createMessage(), {
persistent: false
});
}
};
Activity.prototype._consumeApi = function consumeApi() {
Expand Down
31 changes: 11 additions & 20 deletions dist/eventDefinitions/TimerEventDefinition.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var _piso = require("@0dep/piso");
const kStopped = Symbol.for('stopped');
const kTimerContent = Symbol.for('timerContent');
const kTimer = Symbol.for('timer');
const timerTypes = ['timeDuration', 'timeDate', 'timeCycle'];
function TimerEventDefinition(activity, eventDefinition) {
const type = this.type = eventDefinition.type || 'TimerEventDefinition';
this.activity = activity;
Expand Down Expand Up @@ -81,7 +82,6 @@ TimerEventDefinition.prototype.execute = function execute(executeMessage) {
broker.publish('execution', 'execute.timer', (0, _messageHelper.cloneContent)(timerContent));
broker.publish('event', 'activity.timer', (0, _messageHelper.cloneContent)(timerContent));
if (this.stopped) return;
if (timerContent.timeout === undefined) return this._debug(`waiting for ${timerContent.timerType || 'signal'}`);
if (timerContent.timeout <= 0) return this._completed();
const timers = this.environment.timers.register(timerContent);
const delay = timerContent.timeout;
Expand Down Expand Up @@ -222,28 +222,22 @@ TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
expireAt: new Date(content.expireAt)
})
};
let parseErr;
for (const t of ['timeDuration', 'timeDate', 'timeCycle']) {
if (t in content) result[t] = content[t];else if (t in this) result[t] = this.environment.resolveExpression(this[t], executeMessage);else continue;
for (const timerType of timerTypes) {
if (timerType in content) result[timerType] = content[timerType];else if (timerType in this) result[timerType] = this.environment.resolveExpression(this[timerType], executeMessage);else continue;
let expireAtDate, repeat;
const timerStr = result[t];
const timerStr = result[timerType];
if (timerStr) {
try {
const {
repeat: parsedRepeat,
expireAt: parsedExpireAt
} = this.parse(t, timerStr);
repeat = parsedRepeat;
expireAtDate = parsedExpireAt;
} catch (err) {
parseErr = err;
}
const {
repeat: parsedRepeat,
expireAt: parsedExpireAt
} = this.parse(timerType, timerStr);
repeat = parsedRepeat;
expireAtDate = parsedExpireAt;
} else {
expireAtDate = new Date();
}
if (!expireAtDate) continue;
if (!('expireAt' in result) || result.expireAt > expireAtDate) {
result.timerType = t;
result.timerType = timerType;
result.expireAt = expireAtDate;
result.repeat = repeat;
}
Expand All @@ -255,9 +249,6 @@ TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
} else if (!Object.keys(result).length) {
result.timeout = 0;
}
if (!('timeout' in result) && parseErr) {
this.logger.warn(`<${this.activity.id}> failed to parse timer: ${parseErr.message}`);
}
if (content.inbound && 'repeat' in content.inbound[0]) {
result.repeat = content.inbound[0].repeat;
}
Expand Down
34 changes: 17 additions & 17 deletions docs/TimerEventDefinition.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

TimerEventDefinition behaviour.

# TimerEventDefinition events
## TimerEventDefinition events

The timer event definition publish a number of events.

## `activity.timer`
### `activity.timer`

Fired when the timer is started.

Expand All @@ -19,7 +19,7 @@ Object with properties. A subset:
- `startedAt`: timer started at date
- `expireAt`: timer expires at date

## `activity.timeout`
### `activity.timeout`

Fired when the timer has timed out or was cancelled.

Expand All @@ -29,41 +29,41 @@ Object with `activity.timer` properties and some:
- `stoppedAt`: stopped at date
- `runningTime`: running for milliseconds

# `timeDuration`
## `timeDuration`

Default support for ISO8601 duration. Will set a timer (`setTimeout`) for the duration and then complete when timed out. Invalid ISI8601 duration will stall the execution and wait for cancel.
Default support for ISO8601 duration. Will set a timer (`setTimeout`) for the duration and then complete when timed out. Invalid ISI8601 duration will throw and stop the execution.

Uses [`@0dep/piso`](https://www.npmjs.com/package/@0dep/piso) to parse duration and repetitions. Consequently also [ISO8601 intervals](https://en.wikipedia.org/wiki/ISO_8601) are allowed.
Uses [`@0dep/piso`](https://www.npmjs.com/package/@0dep/piso) to parse duration and repetitions. Consequently [ISO8601 intervals](https://en.wikipedia.org/wiki/ISO_8601) are supported.

# `timeDate`
## `timeDate`

Behaves the same as `timeDuration`. Due date will timeout immediately. An invalid date will stall the execution and wait for cancel.
Behaves the same as `timeDuration`. Due date will timeout immediately. An invalid date, like `2023-02-29`, will throw and stop the execution.

Uses [`@0dep/piso`](https://www.npmjs.com/package/@0dep/piso) to parse date according to [ISO8601](https://en.wikipedia.org/wiki/ISO_8601).

# `timeCycle`

Default support for ISO8601 repeating interval.

If another format is used, e.g. cron, the event definition will wait until cancelled. There are several modules to handle time cycles and this project tries to keep the number of dependencies to a minimum.
## `timeCycle`

Time cycles are parsed with [`@0dep/piso`](https://www.npmjs.com/package/@0dep/piso) that also handles ISO8601 intervals.

# Combined `timeDuration` and `timeDate`
If another format is used, e.g. cron, you need to handle that by [extending the behavior](#set-your-own-timeout). There are several modules to handle time cycles and this project tries to keep the number of dependencies to a minimum.

## Combined `timeDuration` and `timeDate`

The shortest timeout will be picked to start the timer.

# Set your own timeout
## Set your own timeout

If the parent event start message has an `expireAt` date or `timeout` positive integer property a timer will be started.

See how to format these messages [here](/docs/Extension.md).

# Api
Another alternative is to override the [parse function](#timereventdefinitionparsetimertype-value).

## Api

Timer event definition api.

## `TimerEventDefinition.parse(timerType, value)`
### `TimerEventDefinition.parse(timerType, value)`

Parse timer value into expire date.

Expand Down
4 changes: 2 additions & 2 deletions src/activity/Activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ Object.defineProperties(Activity.prototype, {
});

Activity.prototype.activate = function activate() {
if (this[kActivated]) return;
this[kActivated] = true;
this.addInboundListeners();
return this._consumeInbound();
Expand Down Expand Up @@ -877,7 +878,6 @@ Activity.prototype._publishEvent = function publishEvent(state, content, propert
...properties,
type: state,
mandatory: state === 'error',
persistent: 'persistent' in properties ? properties.persistent : state !== 'stop',
});
};

Expand All @@ -897,7 +897,7 @@ Activity.prototype._onStop = function onStop(message) {
if (this.extensions) this.extensions.deactivate(cloneMessage(message));

if (running) {
this._publishEvent('stop', this._createMessage());
this._publishEvent('stop', this._createMessage(), { persistent: false });
}
};

Expand Down
29 changes: 10 additions & 19 deletions src/eventDefinitions/TimerEventDefinition.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const kStopped = Symbol.for('stopped');
const kTimerContent = Symbol.for('timerContent');
const kTimer = Symbol.for('timer');

const timerTypes = ['timeDuration', 'timeDate', 'timeCycle'];

export default function TimerEventDefinition(activity, eventDefinition) {
const type = (this.type = eventDefinition.type || 'TimerEventDefinition');
this.activity = activity;
Expand Down Expand Up @@ -80,7 +82,6 @@ TimerEventDefinition.prototype.execute = function execute(executeMessage) {

if (this.stopped) return;

if (timerContent.timeout === undefined) return this._debug(`waiting for ${timerContent.timerType || 'signal'}`);
if (timerContent.timeout <= 0) return this._completed();

const timers = this.environment.timers.register(timerContent);
Expand Down Expand Up @@ -219,29 +220,23 @@ TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
...('expireAt' in content && { expireAt: new Date(content.expireAt) }),
};

let parseErr;
for (const t of ['timeDuration', 'timeDate', 'timeCycle']) {
if (t in content) result[t] = content[t];
else if (t in this) result[t] = this.environment.resolveExpression(this[t], executeMessage);
for (const timerType of timerTypes) {
if (timerType in content) result[timerType] = content[timerType];
else if (timerType in this) result[timerType] = this.environment.resolveExpression(this[timerType], executeMessage);
else continue;

let expireAtDate, repeat;
const timerStr = result[t];
const timerStr = result[timerType];
if (timerStr) {
try {
const { repeat: parsedRepeat, expireAt: parsedExpireAt } = this.parse(t, timerStr);
repeat = parsedRepeat;
expireAtDate = parsedExpireAt;
} catch (err) {
parseErr = err;
}
const { repeat: parsedRepeat, expireAt: parsedExpireAt } = this.parse(timerType, timerStr);
repeat = parsedRepeat;
expireAtDate = parsedExpireAt;
} else {
expireAtDate = new Date();
}

if (!expireAtDate) continue;
if (!('expireAt' in result) || result.expireAt > expireAtDate) {
result.timerType = t;
result.timerType = timerType;
result.expireAt = expireAtDate;
result.repeat = repeat;
}
Expand All @@ -255,10 +250,6 @@ TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
result.timeout = 0;
}

if (!('timeout' in result) && parseErr) {
this.logger.warn(`<${this.activity.id}> failed to parse timer: ${parseErr.message}`);
}

if (content.inbound && 'repeat' in content.inbound[0]) {
result.repeat = content.inbound[0].repeat;
}
Expand Down
15 changes: 15 additions & 0 deletions test/activity/Activity-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2853,6 +2853,21 @@ describe('Activity', () => {
recovered.getApi().signal();
expect(recovered.counters).to.have.property('taken', 2);
});

it('resume if not running activates activity', () => {
const activity = getActivity(undefined, SignalTaskBehaviour);
activity.resume();

expect(activity.isRunning).to.be.false;
});

it('resume on resume if not running activates activity once', () => {
const activity = getActivity(undefined, SignalTaskBehaviour);
activity.resume();
activity.resume();

expect(activity.isRunning).to.be.false;
});
});

describe('evaluateOutbound()', () => {
Expand Down
Loading

0 comments on commit 79d7324

Please sign in to comment.