From 2adc1e26bcaf4597cdd67d60ff3ca63b4ab355a6 Mon Sep 17 00:00:00 2001 From: Nick Cuthbert Date: Sat, 2 Dec 2017 21:55:46 +0200 Subject: [PATCH] Added after syntax --- lib/actor.js | 5 ++++- lib/index.js | 2 ++ lib/utils.js | 43 +++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- test/actor.js | 22 ++++++++++++++++++---- test/utils.js | 29 +++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 lib/utils.js create mode 100644 test/utils.js diff --git a/lib/actor.js b/lib/actor.js index 42ca410..086e698 100644 --- a/lib/actor.js +++ b/lib/actor.js @@ -32,7 +32,10 @@ class Actor { this.immediate = undefined; this.parent.childSpawned(this); if (shutdown) { - this.shutdownPeriod = shutdown; + if (!shutdown.duration) { + throw new Error('Shutdown should be specified as a duration. It is recommended to use the after() function to do this'); + } + this.shutdownPeriod = shutdown.duration; this.timeout = setTimeout(() => this.stop(), this.shutdownPeriod); } } diff --git a/lib/index.js b/lib/index.js index eb247bc..9e3fe70 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,9 +1,11 @@ const { spawn, spawnStateless } = require('./actor'); const { stop, state$, query, dispatch } = require('./functions'); const { spawnPersistent, configurePersistence } = require('./persistence'); +const { after } = require('./utils'); module.exports = { ...require('./system'), spawn, + after, spawnStateless, query, dispatch, diff --git a/lib/utils.js b/lib/utils.js new file mode 100644 index 0000000..55849a1 --- /dev/null +++ b/lib/utils.js @@ -0,0 +1,43 @@ +class After { + constructor (amount) { + this._amount = amount; + Object.freeze(this); + } + + get hours () { + return { duration: (this._amount * 60 * 60 * 1000) | 0 }; + } + + get hour () { + return this.hours; + } + + get minutes () { + return { duration: (this._amount * 60 * 1000) | 0 }; + } + + get minute () { + return this.minutes; + } + + get seconds () { + return { duration: (this._amount * 1000) | 0 }; + } + + get second () { + return this.seconds; + } + + get milliseconds () { + return { duration: this._amount | 0 }; + } + get millisecond () { + return this.milliseconds; + } +} + +const after = (amount) => new After(amount); + +module.exports = { + after +}; diff --git a/package.json b/package.json index 80b6e87..3baf11c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nact", - "version": "3.1.5", + "version": "3.2.0", "description": "nact ⇒ node.js + actors = your services have never been so µ", "main": "lib/index.js", "scripts": { diff --git a/test/actor.js b/test/actor.js index 78787e3..05baa91 100644 --- a/test/actor.js +++ b/test/actor.js @@ -5,7 +5,7 @@ const chai = require('chai'); const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); chai.should(); -const { start, spawn, spawnStateless, dispatch, stop, query, state$ } = require('../lib'); +const { start, spawn, after, spawnStateless, dispatch, stop, query, state$ } = require('../lib'); const { Promise } = require('bluebird'); const { LocalPath } = require('../lib/paths'); const delay = Promise.delay.bind(Promise); @@ -195,7 +195,7 @@ describe('Actor', function () { }); }); - describe('#stop()', function () { + describe('timeout', function () { let system; beforeEach(() => { system = start(); }); afterEach(() => { @@ -206,19 +206,33 @@ describe('Actor', function () { it('should automatically stop after timeout if timeout is specified', async function () { console.error = ignore; - let child = spawnStateless(system, (msg) => {}, 'test', { shutdown: 100 }); + let child = spawnStateless(system, (msg) => {}, 'test', { shutdown: after(100).milliseconds }); await delay(110); isStopped(child).should.be.true; }); it('should automatically renew timeout after message', async function () { - let child = spawnStateless(system, ignore, 'test1', { shutdown: 60 }); + let child = spawnStateless(system, ignore, 'test1', { shutdown: after(60).milliseconds }); await delay(30); dispatch(child, {}); await delay(40); isStopped(child).should.not.be.true; }); + it('should throw if timeout does not include a duration field', async function () { + (() => spawnStateless(system, ignore, 'test1', { shutdown: {} })).should.throw(); + }); + }); + + describe('#stop()', function () { + let system; + beforeEach(() => { system = start(); }); + afterEach(() => { + stop(system); + // reset console + delete console.error; + }); + it('should prevent children from being spawned after being called', function () { let child = spawnStateless(system, ignore); stop(child); diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 0000000..11505ca --- /dev/null +++ b/test/utils.js @@ -0,0 +1,29 @@ +/* eslint-env mocha */ +/* eslint-disable no-unused-expressions */ +const chai = require('chai'); +chai.should(); +const { after } = require('../lib'); + +describe('#after', function () { + it('should correctly calculate milliseconds', function () { + after(100).milliseconds.duration.should.equal(100); + after(1).millisecond.duration.should.equal(1); + after(0).milliseconds.duration.should.equal(0); + }); + it('should correctly calculate seconds', function () { + after(1).second.duration.should.equal(1000); + after(0).seconds.duration.should.equal(0); + after(10).seconds.duration.should.equal(10000); + after(1.5).seconds.duration.should.equal(1500); + }); + + it('should correctly calculate minutes', function () { + after(1).minute.duration.should.equal(60000); + after(0).minutes.duration.should.equal(0); + }); + + it('should correctly calculate hours', function () { + after(1).hour.duration.should.equal(3600000); + after(0).hours.duration.should.equal(0); + }); +});