keuss 1.6.14 → 1.6.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ #
7
+ # ******** NOTE ********
8
+ # We have attempted to detect the languages in your repository. Please check
9
+ # the `language` matrix defined below to confirm you have the correct set of
10
+ # supported CodeQL languages.
11
+ #
12
+ name: "CodeQL"
13
+
14
+ on:
15
+ push:
16
+ branches: [ master ]
17
+ pull_request:
18
+ # The branches below must be a subset of the branches above
19
+ branches: [ master ]
20
+ schedule:
21
+ - cron: '26 13 * * 1'
22
+
23
+ jobs:
24
+ analyze:
25
+ name: Analyze
26
+ runs-on: ubuntu-latest
27
+ permissions:
28
+ actions: read
29
+ contents: read
30
+ security-events: write
31
+
32
+ strategy:
33
+ fail-fast: false
34
+ matrix:
35
+ language: [ 'javascript' ]
36
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37
+ # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38
+
39
+ steps:
40
+ - name: Checkout repository
41
+ uses: actions/checkout@v3
42
+
43
+ # Initializes the CodeQL tools for scanning.
44
+ - name: Initialize CodeQL
45
+ uses: github/codeql-action/init@v2
46
+ with:
47
+ languages: ${{ matrix.language }}
48
+ # If you wish to specify custom queries, you can do so here or in a config file.
49
+ # By default, queries listed here will override any specified in a config file.
50
+ # Prefix the list here with "+" to use these queries and those in the config file.
51
+
52
+ # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53
+ # queries: security-extended,security-and-quality
54
+
55
+
56
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
57
+ # If this step fails, then you should remove it and run the build manually (see below)
58
+ - name: Autobuild
59
+ uses: github/codeql-action/autobuild@v2
60
+
61
+ # ℹ️ Command-line programs to run using the OS shell.
62
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63
+
64
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
65
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66
+
67
+ # - run: |
68
+ # echo "Run, Build Application using script"
69
+ # ./location_of_script_within_repo/buildscript.sh
70
+
71
+ - name: Perform CodeQL Analysis
72
+ uses: github/codeql-action/analyze@v2
package/Signal.js CHANGED
@@ -73,6 +73,12 @@ class Signal {
73
73
  }
74
74
 
75
75
 
76
+ // to be extended: generic pubsub service
77
+ subscribe_extra (topic, on_cb) {return false}
78
+ unsubscribe_extra (subscr) {}
79
+ emit_extra (topic, ev, cb) {if (cb) cb ();}
80
+
81
+
76
82
  static _hrtimeAsMSecs (hrtime) {
77
83
  return (hrtime[0] * 1000) + (hrtime[1] / 1e6);
78
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keuss",
3
- "version": "1.6.14",
3
+ "version": "1.6.15",
4
4
  "keywords": [
5
5
  "queue",
6
6
  "persistent",
@@ -34,7 +34,8 @@
34
34
  "lodash": "~4.17.21",
35
35
  "mitt": "~3.0.0",
36
36
  "mongodb": "~4.5.0",
37
- "uuid": "~8.3.2"
37
+ "uuid": "~8.3.2",
38
+ "why-is-node-running": "^2.2.2"
38
39
  },
39
40
  "devDependencies": {
40
41
  "chance": "~1.1.8",
@@ -43,6 +44,6 @@
43
44
  },
44
45
  "scripts": {
45
46
  "test": "mocha --reporter spec --check-leaks --no-timeouts --exit test/",
46
- "test-with-coverage": "nyc --reporter=text -- mocha --reporter spec --check-leaks --no-timeouts --exit test/"
47
+ "test-with-coverage": "nyc --reporter=html -- mocha --reporter spec --check-leaks --no-timeouts --exit test/"
47
48
  }
48
49
  }
package/signal/local.js CHANGED
@@ -4,6 +4,7 @@ var Signal = require ('../Signal');
4
4
  var debug = require('debug')('keuss:Signal:local');
5
5
 
6
6
 
7
+ //////////////////////////////////////////////////////////////////////
7
8
  class LocalSignal extends Signal {
8
9
  constructor (queue, factory, opts) {
9
10
  super (queue, opts);
@@ -39,38 +40,110 @@ class LocalSignal extends Signal {
39
40
  debug ('created LocalSignal for channel %s', this._channel);
40
41
  }
41
42
 
42
- type () {return LocalSignalFactory.Type ()}
43
43
 
44
+ //////////////////////////////////////////////////////////////////////
45
+ type () {
46
+ return LocalSignalFactory.Type ();
47
+ }
48
+
49
+
50
+ //////////////////////////////////////////////////////////////////////
44
51
  emitInsertion (mature, cb) {
45
52
  debug ('got insertion event [%o], relay on local mitt', mature);
46
53
  this._factory._emitter.emit (this._channel, mature.getTime () + '');
47
54
  }
48
55
 
56
+ //////////////////////////////////////////////////////////////////////
49
57
  emitPaused (paused, cb) {
50
58
  debug ('got paused event [%d], relay on local mitt', paused);
51
59
  this._factory._emitter.emit (this._channel, `p ${paused}`);
52
60
  }
61
+
62
+
63
+ //////////////////////////////////////////////////////////////////////
64
+ subscribe_extra (topic, on_cb) {
65
+ return this._factory.subscribe_extra (this._master.ns (), topic, on_cb);
66
+ }
67
+
68
+
69
+ //////////////////////////////////////////////////////////////////////
70
+ unsubscribe_extra (subscr) {
71
+ this._factory.unsubscribe_extra (subscr);
72
+ }
73
+
74
+
75
+ //////////////////////////////////////////////////////////////////////
76
+ emit_extra (topic, ev, cb) {
77
+ this._factory.emit_extra (this._master.ns (), topic, ev, cb);
78
+ }
53
79
  }
54
80
 
55
81
 
82
+ //////////////////////////////////////////////////////////////////////
56
83
  class LocalSignalFactory {
57
84
  constructor (opts) {
58
85
  this._emitter = mitt();
86
+ debug ('created local factory');
87
+ }
88
+
89
+
90
+ //////////////////////////////////////////////////////////////////////
91
+ static Type () {
92
+ return 'signal:local';
59
93
  }
60
94
 
61
- static Type () {return 'signal:local'}
62
- type () {return LocalSignalFactory.Type ()}
63
95
 
96
+ //////////////////////////////////////////////////////////////////////
97
+ type () {
98
+ return LocalSignalFactory.Type ();
99
+ }
100
+
101
+
102
+ //////////////////////////////////////////////////////////////////////
64
103
  signal (queue, opts) {
65
104
  return new LocalSignal (queue, this, opts);
66
105
  }
67
106
 
107
+
108
+ //////////////////////////////////////////////////////////////////////
109
+ subscribe_extra (ns, topic, on_cb) {
110
+ const t = `keuss:signal:${ns}:extra:${topic}`;
111
+ debug ('subscribing to ns [%s], topic [%s]', ns, t);
112
+
113
+ const s = {
114
+ n: ns,
115
+ t: t,
116
+ f: (msg => on_cb (msg))
117
+ };
118
+
119
+ this._emitter.on (s.t, s.f);
120
+ return s;
121
+ }
122
+
123
+
124
+ //////////////////////////////////////////////////////////////////////
125
+ unsubscribe_extra (s) {
126
+ this._emitter.off (s.t, s.f);
127
+ debug ('unsubscribed on %s', s.t);
128
+ }
129
+
130
+
131
+ //////////////////////////////////////////////////////////////////////
132
+ emit_extra (ns, topic, ev, cb) {
133
+ const t = `keuss:signal:${ns}:extra:${topic}`;
134
+ debug ('emit extra on topic [%s], value [%j]', t, ev);
135
+ this._emitter.emit (t, ev);
136
+ }
137
+
138
+
139
+ //////////////////////////////////////////////////////////////////////
68
140
  close (cb) {
69
141
  cb ();
70
142
  }
71
143
  }
72
144
 
73
145
 
146
+ //////////////////////////////////////////////////////////////////////
74
147
  function creator (opts, cb) {
75
148
  return cb (null, new LocalSignalFactory (opts));
76
149
  }
@@ -5,7 +5,7 @@ var Signal = require ('../Signal');
5
5
 
6
6
  var debug = require('debug')('keuss:Signal:MongoCapped');
7
7
 
8
-
8
+ //////////////////////////////////////////////////////////////////////
9
9
  class MCSignal extends Signal {
10
10
  constructor (queue, factory, opts) {
11
11
  super (queue, opts);
@@ -45,24 +45,52 @@ class MCSignal extends Signal {
45
45
  debug ('created mongo-capped signaller for topic %s with opts %o', this._topic_name, opts);
46
46
  }
47
47
 
48
+
49
+ //////////////////////////////////////////////////////////////////////
48
50
  type () {return MCSignalFactory.Type ()}
49
51
 
52
+
53
+ //////////////////////////////////////////////////////////////////////
50
54
  emitInsertion (mature, cb) {
51
55
  debug ('emit insertion on topic [%s] value [%d])', this._topic_name, mature);
52
56
  this._factory._channel.publish (this._topic_name, mature.getTime());
53
57
  }
54
58
 
59
+
60
+ //////////////////////////////////////////////////////////////////////
55
61
  emitPaused (paused, cb) {
56
62
  debug ('emit paused on topic [%s], value [%b]', this._topic_name, paused);
57
63
  this._factory._channel.publish (this._topic_name, `p ${paused}`);
58
64
  }
59
65
 
66
+
67
+ //////////////////////////////////////////////////////////////////////
60
68
  _insertionEvent (mature) {
61
69
  debug ('got insertion event on ch [%s], mature is %s, calling master.emitInsertion()', this._channel, mature);
62
70
  this._master.signalInsertion (new Date (mature));
63
71
  }
72
+
73
+
74
+ //////////////////////////////////////////////////////////////////////
75
+ subscribe_extra (topic, on_cb) {
76
+ return this._factory.subscribe_extra (this._master.ns (), topic, on_cb);
77
+ }
78
+
79
+
80
+ //////////////////////////////////////////////////////////////////////
81
+ unsubscribe_extra (subscr) {
82
+ this._factory.unsubscribe_extra (subscr);
83
+ }
84
+
85
+
86
+ //////////////////////////////////////////////////////////////////////
87
+ emit_extra (topic, ev, cb) {
88
+ this._factory.emit_extra (this._master.ns (), topic, ev, cb);
89
+ }
64
90
  }
65
91
 
92
+
93
+ //////////////////////////////////////////////////////////////////////
66
94
  class MCSignalFactory {
67
95
  constructor (opts) {
68
96
  var defaults = {
@@ -79,19 +107,56 @@ class MCSignalFactory {
79
107
  debug ('created mongo-capped factory with opts %o', opts);
80
108
  }
81
109
 
82
- static Type () {return 'signal:mongo-capped'}
83
- type () {return MCSignalFactory.Type ()}
84
110
 
111
+ //////////////////////////////////////////////////////////////////////
112
+ static Type () {
113
+ return 'signal:mongo-capped';
114
+ }
115
+
116
+
117
+ //////////////////////////////////////////////////////////////////////
118
+ type () {
119
+ return MCSignalFactory.Type ();
120
+ }
121
+
122
+
123
+ //////////////////////////////////////////////////////////////////////
85
124
  signal (channel, opts) {
86
125
  return new MCSignal (channel, this, opts);
87
126
  }
88
127
 
128
+
129
+ //////////////////////////////////////////////////////////////////////
130
+ subscribe_extra (ns, topic, on_cb) {
131
+ const t = `keuss:signal:${ns}:extra:${topic}`;
132
+ debug ('subscribing to ns [%s], topic [%s]', ns, t);
133
+ return this._channel.subscribe (t, on_cb);
134
+ }
135
+
136
+
137
+ //////////////////////////////////////////////////////////////////////
138
+ unsubscribe_extra (subscr) {
139
+ subscr.unsubscribe ();
140
+ debug ('unsubscribed on %j', subscr);
141
+ }
142
+
143
+
144
+ //////////////////////////////////////////////////////////////////////
145
+ emit_extra (ns, topic, ev, cb) {
146
+ const t = `keuss:signal:${ns}:extra:${topic}`;
147
+ debug ('emit extra on ns [%s], topic [%s], value [%j]', ns, t, ev);
148
+ this._channel.publish (t, ev);
149
+ }
150
+
151
+
152
+ //////////////////////////////////////////////////////////////////////
89
153
  close (cb) {
90
154
  this._mubsub.close (cb);
91
155
  }
92
156
  }
93
157
 
94
158
 
159
+ //////////////////////////////////////////////////////////////////////
95
160
  function creator (opts, cb) {
96
161
  return cb (null, new MCSignalFactory (opts));
97
162
  }
@@ -8,6 +8,7 @@ var Signal = require ('../Signal');
8
8
  var debug = require('debug')('keuss:Signal:RedisPubsub');
9
9
 
10
10
 
11
+ //////////////////////////////////////////////////////////////////////
11
12
  class RPSSignal extends Signal {
12
13
  constructor (queue, factory, opts) {
13
14
  super (queue, opts);
@@ -53,24 +54,54 @@ class RPSSignal extends Signal {
53
54
  debug ('created redis-pubsub signaller for topic %s with opts %o', this._topic_name, opts);
54
55
  }
55
56
 
56
- type () {return RPSSignalFactory.Type ()}
57
57
 
58
+ //////////////////////////////////////////////////////////////////////
59
+ type () {
60
+ return RPSSignalFactory.Type ();
61
+ }
62
+
63
+
64
+ //////////////////////////////////////////////////////////////////////
58
65
  emitInsertion (mature, cb) {
59
66
  debug ('emit insertion on channel [%s] value [%d])', this._channel, mature);
60
67
  this._rediscl_pub.publish (this._channel, mature.getTime());
61
68
  }
62
69
 
70
+
71
+ //////////////////////////////////////////////////////////////////////
63
72
  emitPaused (paused, cb) {
64
73
  debug ('emit paused on channel [%s], value [%b]', this._channel, paused);
65
74
  this._rediscl_pub.publish (this._channel, `p ${paused}`);
66
75
  }
67
76
 
77
+
78
+ //////////////////////////////////////////////////////////////////////
68
79
  _insertionEvent (mature) {
69
80
  debug ('got insertion event on ch [%s], mature is %s, calling master.emitInsertion()', this._channel, mature);
70
81
  this._master.signalInsertion (new Date (mature));
71
82
  }
83
+
84
+
85
+ //////////////////////////////////////////////////////////////////////
86
+ subscribe_extra (topic, on_cb) {
87
+ return this._factory.subscribe_extra (this._master.ns (), topic, on_cb);
88
+ }
89
+
90
+
91
+ //////////////////////////////////////////////////////////////////////
92
+ unsubscribe_extra (subscr) {
93
+ this._factory.unsubscribe_extra (subscr);
94
+ }
95
+
96
+
97
+ //////////////////////////////////////////////////////////////////////
98
+ emit_extra (topic, ev, cb) {
99
+ this._factory.emit_extra (this._master.ns (), topic, ev, cb);
100
+ }
72
101
  }
73
102
 
103
+
104
+ //////////////////////////////////////////////////////////////////////
74
105
  class RPSSignalFactory {
75
106
  constructor (opts) {
76
107
  this._opts = opts || {};
@@ -86,14 +117,61 @@ class RPSSignalFactory {
86
117
  debug ('created redis-pubsub factory with opts %o', opts);
87
118
  }
88
119
 
89
- static Type () {return 'signal:redis-pubsub'}
90
- type () {return RPSSignalFactory.Type ()}
91
120
 
121
+ //////////////////////////////////////////////////////////////////////
122
+ static Type () {
123
+ return 'signal:redis-pubsub';
124
+ }
125
+
126
+
127
+ //////////////////////////////////////////////////////////////////////
128
+ type () {
129
+ return RPSSignalFactory.Type ();
130
+ }
131
+
132
+
133
+ //////////////////////////////////////////////////////////////////////
92
134
  signal (channel, opts) {
93
135
  debug ('creating redis-pubsub signaller with opts %o', opts);
94
136
  return new RPSSignal (channel, this, opts);
95
137
  }
96
138
 
139
+
140
+ //////////////////////////////////////////////////////////////////////
141
+ subscribe_extra (ns, topic, on_cb) {
142
+ const t = `keuss:signal:${ns}:extra:${topic}`;
143
+ debug ('subscribing to ns [%s], topic [%s]', ns, t);
144
+
145
+ const s = {
146
+ n: ns,
147
+ t: t,
148
+ f: (msg => on_cb (JSON.parse (msg)))
149
+ };
150
+
151
+ this._emitter.on (s.t, s.f);
152
+ this._rediscl_sub.subscribe (s.t);
153
+ return s;
154
+ }
155
+
156
+
157
+ //////////////////////////////////////////////////////////////////////
158
+ unsubscribe_extra (subscr) {
159
+ this._rediscl_sub.unsubscribe (subscr.t);
160
+ this._emitter.off (subscr.t, subscr.f);
161
+ debug ('unsubscribed on %j', subscr);
162
+ }
163
+
164
+
165
+ //////////////////////////////////////////////////////////////////////
166
+ emit_extra (ns, topic, ev, cb) {
167
+ const t = `keuss:signal:${ns}:extra:${topic}`;
168
+ const v = JSON.stringify(ev);
169
+ debug ('emit extra on ns [%s], topic [%s], value [%j]', ns, t, ev);
170
+ this._rediscl_pub.publish (t, v);
171
+ }
172
+
173
+
174
+ //////////////////////////////////////////////////////////////////////
97
175
  close (cb) {
98
176
  async.parallel ([
99
177
  cb => this._rediscl_pub.quit (cb),
@@ -103,6 +181,7 @@ class RPSSignalFactory {
103
181
  }
104
182
 
105
183
 
184
+ //////////////////////////////////////////////////////////////////////
106
185
  function creator (opts, cb) {
107
186
  return cb (null, new RPSSignalFactory (opts));
108
187
  }
package/test/signal.js ADDED
@@ -0,0 +1,161 @@
1
+ const should = require ('should');
2
+ const async = require ('async');
3
+ const _ = require ('lodash');
4
+
5
+ const Local = require ('../signal/local');
6
+ const Redis = require ('../signal/redis-pubsub');
7
+ const Mongo = require ('../signal/mongo-capped');
8
+
9
+ // const whyIsNodeRunning = require('why-is-node-running');
10
+
11
+ const MongoClient = require ('mongodb').MongoClient;
12
+
13
+ // setTimeout (() => whyIsNodeRunning(), 9000)
14
+
15
+ _.forEach ({
16
+ Local,
17
+ Redis,
18
+ Mongo
19
+ }, (CL, CLName) => {
20
+ describe (`${CLName} signaller`, () => {
21
+
22
+ before (done => {
23
+ done();
24
+ });
25
+
26
+ after (done => async.series ([
27
+ cb => setTimeout (cb, 1000),
28
+ cb => MongoClient.connect ('mongodb://localhost/keuss_signal', (err, cl) => {
29
+ if (err) return done (err);
30
+ cl.db().dropDatabase (() => cl.close (cb))
31
+ })
32
+ ], done));
33
+
34
+
35
+ it ('creates ok', done => {
36
+ CL ({}, (err, factory) => {
37
+ if (err) return done(err);
38
+ const q = {ns() {return 'the-ns'}, name () {return 'the-queue'}};
39
+ const signal = factory.signal (q, {});
40
+ setTimeout (() => factory.close(done), 500);
41
+ });
42
+ });
43
+
44
+
45
+ describe (`extra/generic pubsub`, () => {
46
+ it ('subscribes and receives info ok on 3 subscribers', done => {
47
+ CL ({}, (err, factory) => {
48
+ if (err) return done(err);
49
+ const q = {ns() {return 'the-ns'}, name () {return 'the-queue'}};
50
+ const signal1 = factory.signal (q, {});
51
+ const signal2 = factory.signal (q, {});
52
+ const signal3 = factory.signal (q, {});
53
+
54
+ const evs = [];
55
+
56
+ function manage (ev) {
57
+ evs.push (ev);
58
+ if (evs.length == 3) {
59
+ evs.should.eql ([
60
+ { a: 1, b: 'ertwetr' },
61
+ { a: 1, b: 'ertwetr' },
62
+ { a: 1, b: 'ertwetr' }
63
+ ]);
64
+
65
+ factory.close(done);
66
+ }
67
+ }
68
+
69
+ signal1.subscribe_extra ('the-topic', manage);
70
+ signal2.subscribe_extra ('the-topic', manage);
71
+ signal3.subscribe_extra ('the-topic', manage);
72
+
73
+ setTimeout (() => signal2.emit_extra ('the-topic', {a:1, b:'ertwetr'}), 100);
74
+ });
75
+ });
76
+
77
+
78
+ it ('functions across several queues on the same signaller', done => {
79
+ CL ({}, (err, factory) => {
80
+ if (err) return done(err);
81
+ const signal1 = factory.signal ({ns() {return 'the-ns'}, name () {return 'the-queue-1'}}, {});
82
+ const signal2 = factory.signal ({ns() {return 'the-ns'}, name () {return 'the-queue-2'}}, {});
83
+ const signal3 = factory.signal ({ns() {return 'the-ns'}, name () {return 'the-queue-3'}}, {});
84
+
85
+ const evs = [];
86
+
87
+ function manage (ev) {
88
+ evs.push (ev);
89
+ if (evs.length == 3) {
90
+ evs.should.eql ([
91
+ { a: 1, b: 'ertwetr' },
92
+ { a: 1, b: 'ertwetr' },
93
+ { a: 1, b: 'ertwetr' }
94
+ ]);
95
+
96
+ factory.close(done);
97
+ }
98
+ }
99
+
100
+ signal1.subscribe_extra ('the-topic', manage);
101
+ signal2.subscribe_extra ('the-topic', manage);
102
+ signal3.subscribe_extra ('the-topic', manage);
103
+
104
+ setTimeout (() => signal2.emit_extra ('the-topic', {a:1, b:'ertwetr'}), 100);
105
+ });
106
+ });
107
+
108
+ it ('isolates namespaces', done => {
109
+ CL ({}, (err, factory) => {
110
+ if (err) return done(err);
111
+ const signal1 = factory.signal ({ns() {return 'the-ns-1'}, name () {return 'the-queue'}}, {});
112
+ const signal2 = factory.signal ({ns() {return 'the-ns-2'}, name () {return 'the-queue'}}, {});
113
+
114
+ const evs = [];
115
+
116
+ async.series ([
117
+ cb => {signal1.subscribe_extra ('the-topic', ev => evs.push ({src: 1, ev})); cb ();},
118
+ cb => {signal2.subscribe_extra ('the-topic', ev => evs.push ({src: 2, ev})); cb ();},
119
+ cb => setTimeout (() => {signal1.emit_extra ('the-topic', {a:1, b:'qwertyuiop'}); cb ()}, 100),
120
+ cb => setTimeout (() => {signal2.emit_extra ('the-topic', {a:2, b:'asdfghjkl'}); cb ()}, 100),
121
+ cb => setTimeout (cb, 100),
122
+ ], err => {
123
+ if (err) return done(err);
124
+ evs.should.eql ([
125
+ { src: 1, ev: { a: 1, b: 'qwertyuiop' } },
126
+ { src: 2, ev: { a: 2, b: 'asdfghjkl' } }
127
+ ]);
128
+ factory.close(done);
129
+ });
130
+ });
131
+ });
132
+
133
+ it ('unsubscribes ok and ceases to receive info', done => {
134
+ CL ({}, (err, factory) => {
135
+ if (err) return done(err);
136
+ const signal1 = factory.signal ({ns() {return 'the-ns'}, name () {return 'the-queue'}}, {});
137
+
138
+ const evs = [];
139
+
140
+ function manage (ev) { evs.push (ev); }
141
+
142
+ let subscr = null;
143
+ async.series ([
144
+ cb => {subscr = signal1.subscribe_extra ('the-topic', manage); cb ();},
145
+ cb => setTimeout (() => {signal1.emit_extra ('the-topic', {a:1, b:'ertwetr'}); cb ()}, 100),
146
+ cb => setTimeout (cb, 100),
147
+ cb => {signal1.unsubscribe_extra (subscr); cb (); },
148
+ cb => setTimeout (() => {signal1.emit_extra ('the-topic', {a:2, b:'asdfghjk'}); cb ()}, 100),
149
+ ], err => {
150
+ if (err) return done(err);
151
+ evs.should.eql ([ { a: 1, b: 'ertwetr' } ]);
152
+ factory.close(done);
153
+ });
154
+ });
155
+ });
156
+
157
+ });
158
+
159
+
160
+ });
161
+ });