keuss 2.0.7 → 2.2.0
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.
- package/.mocharc.yaml +3 -0
- package/Pipeline/BaseLink.js +1 -1
- package/Pipeline/Queue.js +114 -89
- package/Queue.js +15 -2
- package/backends/bucket-mongo-safe.js +166 -145
- package/backends/intraorder.js +94 -83
- package/backends/mongo.js +147 -95
- package/backends/pl-mongo.js +20 -31
- package/backends/postgres.js +16 -3
- package/backends/ps-mongo.js +131 -110
- package/backends/redis-list.js +2 -1
- package/backends/redis-oq.js +2 -3
- package/backends/stream-mongo.js +83 -64
- package/lib/mubsub/channel.js +313 -0
- package/lib/mubsub/connection.js +79 -0
- package/lib/mubsub/index.js +10 -0
- package/package.json +5 -7
- package/signal/mongo-capped.js +1 -1
- package/stats/mongo.js +91 -54
- package/utils/RedisOrderedQueue.js +23 -3
package/backends/mongo.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
const _ = require ('lodash');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const MongoClient = require ('mongodb').MongoClient;
|
|
4
|
+
const mongo = require ('mongodb');
|
|
5
|
+
const debug = require('debug')('keuss:Queue:mongo');
|
|
6
|
+
|
|
7
|
+
const Queue = require ('../Queue');
|
|
8
|
+
const QFactory_MongoDB_defaults = require ('../QFactory-MongoDB-defaults');
|
|
5
9
|
|
|
6
|
-
var Queue = require ('../Queue');
|
|
7
|
-
var QFactory_MongoDB_defaults = require ('../QFactory-MongoDB-defaults');
|
|
8
10
|
|
|
9
11
|
class SimpleMongoQueue extends Queue {
|
|
10
12
|
|
|
@@ -20,187 +22,237 @@ class SimpleMongoQueue extends Queue {
|
|
|
20
22
|
return 'mongo:simple';
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
|
|
23
26
|
/////////////////////////////////////////
|
|
24
27
|
type () {
|
|
25
28
|
return 'mongo:simple';
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
|
|
28
32
|
/////////////////////////////////////////
|
|
29
33
|
// add element to queue
|
|
30
|
-
insert (entry,
|
|
31
|
-
this._col.insertOne (entry
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
insert (entry, cb) {
|
|
35
|
+
this._col.insertOne (entry)
|
|
36
|
+
.then (res => {
|
|
37
|
+
debug ('inserted entry %j -> %j', entry, res)
|
|
38
|
+
cb (null, res.insertedId);
|
|
39
|
+
})
|
|
40
|
+
.catch (err => {
|
|
41
|
+
if (err.code == 11000) {
|
|
42
|
+
const e = new Error (`duplicated entry with _id ${entry._id}`)
|
|
43
|
+
e.code = 'EDUP';
|
|
44
|
+
cb(e)
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
cb (err)
|
|
48
|
+
}
|
|
34
49
|
});
|
|
35
50
|
}
|
|
36
|
-
|
|
51
|
+
c
|
|
37
52
|
|
|
38
53
|
/////////////////////////////////////////
|
|
39
54
|
// get element from queue
|
|
40
|
-
get (
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
get (cb) {
|
|
56
|
+
const query = {
|
|
57
|
+
mature: {$lte: Queue.nowPlusSecs (0)}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const opts = {
|
|
61
|
+
sort: {mature : 1},
|
|
62
|
+
includeResultMetadata: true
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
this._col.findOneAndDelete (query, opts)
|
|
66
|
+
.then (result => {
|
|
67
|
+
debug ('get() element, findOneAndDelete returned %j', result)
|
|
43
68
|
const v = result && result.value;
|
|
44
|
-
if (!v) return
|
|
69
|
+
if (!v) return cb ();
|
|
45
70
|
if (v.payload._bsontype == 'Binary') v.payload = v.payload.buffer;
|
|
46
|
-
|
|
47
|
-
})
|
|
71
|
+
cb (null, v);
|
|
72
|
+
})
|
|
73
|
+
.catch (cb);
|
|
48
74
|
}
|
|
49
|
-
|
|
75
|
+
|
|
50
76
|
|
|
51
77
|
//////////////////////////////////
|
|
52
78
|
// reserve element: call cb (err, pl) where pl has an id
|
|
53
|
-
reserve (
|
|
54
|
-
|
|
79
|
+
reserve (cb) {
|
|
80
|
+
const delay = this._opts.reserve_delay || 120;
|
|
55
81
|
|
|
56
|
-
|
|
82
|
+
const query = {
|
|
57
83
|
mature: {$lte: Queue.nowPlusSecs (0)}
|
|
58
84
|
};
|
|
59
85
|
|
|
60
|
-
|
|
86
|
+
const update = {
|
|
61
87
|
$set: {mature: Queue.nowPlusSecs (delay), reserved: new Date ()},
|
|
62
88
|
$inc: {tries: 1}
|
|
63
89
|
};
|
|
64
90
|
|
|
65
|
-
|
|
91
|
+
const opts = {
|
|
66
92
|
sort: {mature : 1},
|
|
67
|
-
returnDocument: 'before'
|
|
93
|
+
returnDocument: 'before',
|
|
94
|
+
includeResultMetadata: true
|
|
68
95
|
};
|
|
69
96
|
|
|
70
|
-
this._col.findOneAndUpdate (query, update, opts
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
97
|
+
this._col.findOneAndUpdate (query, update, opts)
|
|
98
|
+
.then (res => {
|
|
99
|
+
debug ('reserve() element, findOneAndUpdate returned %j', res)
|
|
100
|
+
const v = res && res.value;
|
|
101
|
+
if (!v) return cb ();
|
|
74
102
|
if (v.payload._bsontype == 'Binary') v.payload = v.payload.buffer;
|
|
75
|
-
|
|
76
|
-
})
|
|
103
|
+
cb (null, v);
|
|
104
|
+
})
|
|
105
|
+
.catch (cb);
|
|
77
106
|
}
|
|
78
107
|
|
|
79
108
|
|
|
80
109
|
//////////////////////////////////
|
|
81
110
|
// commit previous reserve, by p.id
|
|
82
|
-
commit (id,
|
|
111
|
+
commit (id, cb) {
|
|
112
|
+
const query = {
|
|
113
|
+
reserved: {$exists: true}
|
|
114
|
+
};
|
|
115
|
+
|
|
83
116
|
try {
|
|
84
|
-
|
|
85
|
-
_id: (_.isString(id) ? new mongo.ObjectID (id) : id),
|
|
86
|
-
reserved: {$exists: true}
|
|
87
|
-
};
|
|
117
|
+
query._id = (_.isString(id) ? new mongo.ObjectId (id) : id);
|
|
88
118
|
}
|
|
89
119
|
catch (e) {
|
|
90
|
-
return
|
|
120
|
+
return cb ('id [' + id + '] can not be used as rollback id: ' + e);
|
|
91
121
|
}
|
|
92
122
|
|
|
93
|
-
this._col.deleteOne (query, {}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
123
|
+
this._col.deleteOne (query, {})
|
|
124
|
+
.then (res => {
|
|
125
|
+
debug ('commit(%s) element, deleteOne returned %j', id, res)
|
|
126
|
+
cb (null, res && (res.deletedCount == 1));
|
|
127
|
+
})
|
|
128
|
+
.catch (cb);
|
|
97
129
|
}
|
|
98
130
|
|
|
99
131
|
|
|
100
132
|
//////////////////////////////////
|
|
101
133
|
// rollback previous reserve, by p.id
|
|
102
|
-
rollback (id, next_t,
|
|
134
|
+
rollback (id, next_t, cb) {
|
|
103
135
|
if (_.isFunction (next_t)) {
|
|
104
|
-
|
|
136
|
+
cb = next_t;
|
|
105
137
|
next_t = null;
|
|
106
138
|
}
|
|
107
139
|
|
|
140
|
+
const query = {
|
|
141
|
+
reserved: {$exists: true}
|
|
142
|
+
};
|
|
143
|
+
|
|
108
144
|
try {
|
|
109
|
-
|
|
110
|
-
_id: (_.isString(id) ? new mongo.ObjectID (id) : id),
|
|
111
|
-
reserved: {$exists: true}
|
|
112
|
-
};
|
|
145
|
+
query ._id = (_.isString(id) ? new mongo.ObjectId (id) : id);
|
|
113
146
|
}
|
|
114
147
|
catch (e) {
|
|
115
|
-
return
|
|
148
|
+
return cb ('id [' + id + '] can not be used as rollback id: ' + e);
|
|
116
149
|
}
|
|
117
150
|
|
|
118
|
-
|
|
151
|
+
const update = {
|
|
119
152
|
$set: {mature: (next_t ? new Date (next_t) : Queue.now ())},
|
|
120
153
|
$unset: {reserved: ''}
|
|
121
154
|
};
|
|
122
155
|
|
|
123
|
-
this._col.updateOne (query, update, {}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
156
|
+
this._col.updateOne (query, update, {})
|
|
157
|
+
.then (res => {
|
|
158
|
+
debug ('rollback(%s) element, updateOne returned %j', id, res)
|
|
159
|
+
cb (null, res && (res.modifiedCount == 1));
|
|
160
|
+
})
|
|
161
|
+
.catch (cb);
|
|
127
162
|
}
|
|
128
163
|
|
|
129
164
|
|
|
130
165
|
//////////////////////////////////
|
|
131
166
|
// queue size including non-mature elements
|
|
132
|
-
totalSize (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
this._col.countDocuments (q, opts
|
|
167
|
+
totalSize (cb) {
|
|
168
|
+
const q = {};
|
|
169
|
+
const opts = {};
|
|
170
|
+
this._col.countDocuments (q, opts)
|
|
171
|
+
.then (res => cb (null, res))
|
|
172
|
+
.catch (cb);
|
|
136
173
|
}
|
|
137
174
|
|
|
138
175
|
|
|
139
176
|
//////////////////////////////////
|
|
140
177
|
// queue size NOT including non-mature elements
|
|
141
|
-
size (
|
|
142
|
-
|
|
178
|
+
size (cb) {
|
|
179
|
+
const q = {
|
|
143
180
|
mature : {$lte : Queue.now ()}
|
|
144
181
|
};
|
|
145
182
|
|
|
146
|
-
|
|
147
|
-
this._col.countDocuments (q, opts
|
|
183
|
+
const opts = {};
|
|
184
|
+
this._col.countDocuments (q, opts)
|
|
185
|
+
.then (res => cb (null, res))
|
|
186
|
+
.catch (cb);
|
|
148
187
|
}
|
|
149
188
|
|
|
150
189
|
|
|
151
190
|
//////////////////////////////////
|
|
152
191
|
// queue size of non-mature elements only
|
|
153
|
-
schedSize (
|
|
154
|
-
|
|
192
|
+
schedSize (cb) {
|
|
193
|
+
const q = {
|
|
155
194
|
mature : {$gt : Queue.now ()},
|
|
156
195
|
reserved: {$exists: false}
|
|
157
196
|
};
|
|
158
197
|
|
|
159
|
-
|
|
160
|
-
this._col.countDocuments (q, opts
|
|
198
|
+
const opts = {};
|
|
199
|
+
this._col.countDocuments (q, opts)
|
|
200
|
+
.then (res => cb (null, res))
|
|
201
|
+
.catch (cb);
|
|
161
202
|
}
|
|
162
203
|
|
|
163
204
|
|
|
164
205
|
//////////////////////////////////
|
|
165
206
|
// queue size of reserved elements only
|
|
166
|
-
resvSize (
|
|
167
|
-
|
|
207
|
+
resvSize (cb) {
|
|
208
|
+
const q = {
|
|
168
209
|
mature : {$gt : Queue.now ()},
|
|
169
210
|
reserved: {$exists: true}
|
|
170
211
|
};
|
|
171
212
|
|
|
172
|
-
|
|
173
|
-
this._col.countDocuments (q, opts
|
|
213
|
+
const opts = {};
|
|
214
|
+
this._col.countDocuments (q, opts)
|
|
215
|
+
.then (res => cb (null, res))
|
|
216
|
+
.catch (cb);
|
|
174
217
|
}
|
|
175
218
|
|
|
176
219
|
|
|
177
220
|
/////////////////////////////////////////
|
|
178
221
|
// get element from queue
|
|
179
|
-
next_t (
|
|
180
|
-
this._col.find ({})
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
})
|
|
222
|
+
next_t (cb) {
|
|
223
|
+
this._col.find ({})
|
|
224
|
+
.limit(1)
|
|
225
|
+
.sort ({mature:1})
|
|
226
|
+
.project ({mature:1})
|
|
227
|
+
.next ()
|
|
228
|
+
.then (res => {
|
|
229
|
+
debug ('next_t(), find returned %j', res)
|
|
230
|
+
cb (null, res && res.mature);
|
|
231
|
+
})
|
|
232
|
+
.catch (cb);
|
|
184
233
|
}
|
|
185
234
|
|
|
186
235
|
|
|
187
236
|
//////////////////////////////////////////////
|
|
188
237
|
// remove by id
|
|
189
|
-
remove (id,
|
|
238
|
+
remove (id, cb) {
|
|
239
|
+
const query = {
|
|
240
|
+
reserved: {$exists: false}
|
|
241
|
+
};
|
|
242
|
+
|
|
190
243
|
try {
|
|
191
|
-
|
|
192
|
-
_id: (_.isString(id) ? new mongo.ObjectID (id) : id),
|
|
193
|
-
reserved: {$exists: false}
|
|
194
|
-
};
|
|
244
|
+
query._id = (_.isString(id) ? new mongo.ObjectId (id) : id);
|
|
195
245
|
}
|
|
196
246
|
catch (e) {
|
|
197
|
-
return
|
|
247
|
+
return cb ('id [' + id + '] can not be used as remove id: ' + e);
|
|
198
248
|
}
|
|
199
249
|
|
|
200
|
-
this._col.deleteOne (query, {}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
250
|
+
this._col.deleteOne (query, {})
|
|
251
|
+
.then (res => {
|
|
252
|
+
debug ('remove(%s) element, deleteOne returned %j', id, res)
|
|
253
|
+
cb (null, res && (res.deletedCount == 1));
|
|
254
|
+
})
|
|
255
|
+
.catch (cb)
|
|
204
256
|
}
|
|
205
257
|
|
|
206
258
|
|
|
@@ -210,11 +262,14 @@ class SimpleMongoQueue extends Queue {
|
|
|
210
262
|
//////////////////////////////////////////////////////////////////
|
|
211
263
|
// create needed indexes for O(1) functioning
|
|
212
264
|
_ensureIndexes (cb) {
|
|
213
|
-
this._col.createIndex ({mature : 1}
|
|
265
|
+
this._col.createIndex ({mature : 1})
|
|
266
|
+
.then (() => cb (null, this))
|
|
267
|
+
.catch (cb);
|
|
214
268
|
}
|
|
215
269
|
};
|
|
216
270
|
|
|
217
271
|
|
|
272
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
218
273
|
class Factory extends QFactory_MongoDB_defaults {
|
|
219
274
|
constructor (opts, mongo_conn) {
|
|
220
275
|
super (opts);
|
|
@@ -256,25 +311,22 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
256
311
|
reserve: true,
|
|
257
312
|
pipeline: false,
|
|
258
313
|
tape: false,
|
|
259
|
-
remove: true
|
|
314
|
+
remove: true,
|
|
315
|
+
id: true,
|
|
260
316
|
};
|
|
261
317
|
}
|
|
262
318
|
}
|
|
263
319
|
|
|
264
320
|
function creator (opts, cb) {
|
|
265
|
-
|
|
266
|
-
|
|
321
|
+
const _opts = opts || {};
|
|
322
|
+
const m_url = _opts.url || 'mongodb://localhost:27017/keuss';
|
|
267
323
|
|
|
268
|
-
MongoClient.connect (m_url
|
|
269
|
-
|
|
270
|
-
|
|
324
|
+
MongoClient.connect (m_url)
|
|
325
|
+
.then (cl => {
|
|
326
|
+
const F = new Factory (_opts, cl);
|
|
271
327
|
F.async_init (err => cb (null, F));
|
|
272
|
-
})
|
|
328
|
+
})
|
|
329
|
+
.catch (cb);
|
|
273
330
|
}
|
|
274
331
|
|
|
275
332
|
module.exports = creator;
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
package/backends/pl-mongo.js
CHANGED
|
@@ -31,7 +31,8 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
31
31
|
}
|
|
32
32
|
}, {
|
|
33
33
|
upsert: true
|
|
34
|
-
})
|
|
34
|
+
})
|
|
35
|
+
.finally (() => {});
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
|
|
@@ -98,9 +99,8 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
98
99
|
}
|
|
99
100
|
}, {
|
|
100
101
|
upsert: true
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
})
|
|
103
|
+
.finally (() => {});
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
|
|
@@ -141,11 +141,15 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
141
141
|
close (cb) {
|
|
142
142
|
super.close (() => {
|
|
143
143
|
async.parallel ([
|
|
144
|
-
cb => this._mongo_data_conn.close (cb),
|
|
145
|
-
cb => this._mongo_topology_conn.close (cb)
|
|
146
|
-
]
|
|
144
|
+
cb => this._mongo_data_conn.close ().then (res => cb (null, res)).catch (cb),
|
|
145
|
+
cb => this._mongo_topology_conn.close ().then (res => cb (null, res)).catch (cb),
|
|
146
|
+
])
|
|
147
|
+
.then (res => {
|
|
147
148
|
this._mongo_data_conn = null;
|
|
148
149
|
this._mongo_topology_conn = null;
|
|
150
|
+
if (cb) return cb ();
|
|
151
|
+
})
|
|
152
|
+
.catch (err => {
|
|
149
153
|
if (cb) return cb (err);
|
|
150
154
|
});
|
|
151
155
|
});
|
|
@@ -165,7 +169,8 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
165
169
|
reserve: true,
|
|
166
170
|
pipeline: true,
|
|
167
171
|
tape: false,
|
|
168
|
-
remove: true
|
|
172
|
+
remove: true,
|
|
173
|
+
id: true,
|
|
169
174
|
};
|
|
170
175
|
}
|
|
171
176
|
|
|
@@ -194,30 +199,14 @@ function creator (opts, cb) {
|
|
|
194
199
|
}
|
|
195
200
|
|
|
196
201
|
async.series ([
|
|
197
|
-
cb => MongoClient.connect (m_url
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
debug ('connected OK to data mongoDB %s', m_url);
|
|
204
|
-
cb (null, cl);
|
|
205
|
-
}),
|
|
206
|
-
cb => MongoClient.connect (m_topology_url, { useNewUrlParser: true }, (err, cl) => {
|
|
207
|
-
if (err) {
|
|
208
|
-
debug ('error while connecting to topology mongoDB [%s]', m_topology_url, err);
|
|
209
|
-
return cb (err);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
debug ('connected OK to topology mongoDB %s', m_topology_url);
|
|
213
|
-
cb (null, cl);
|
|
214
|
-
}),
|
|
215
|
-
], (err, res) => {
|
|
216
|
-
if (err) return cb (err);
|
|
217
|
-
|
|
218
|
-
var F = new Factory (_opts, res[0], res[1]);
|
|
202
|
+
cb => MongoClient.connect (m_url).then (res => cb (null, res)).catch (cb),
|
|
203
|
+
cb => MongoClient.connect (m_topology_url).then (res => cb (null, res)).catch (cb),
|
|
204
|
+
])
|
|
205
|
+
.then (res => {
|
|
206
|
+
const F = new Factory (_opts, res[0], res[1]);
|
|
219
207
|
F.async_init (err => cb (null, F));
|
|
220
|
-
})
|
|
208
|
+
})
|
|
209
|
+
.catch (cb);
|
|
221
210
|
}
|
|
222
211
|
|
|
223
212
|
module.exports = creator;
|
package/backends/postgres.js
CHANGED
|
@@ -58,7 +58,7 @@ class PGQueue extends Queue {
|
|
|
58
58
|
/////////////////////////////////////////
|
|
59
59
|
// add element to queue
|
|
60
60
|
insert (entry, cb) {
|
|
61
|
-
const _id = entry.
|
|
61
|
+
const _id = entry._id || uuid.v4();
|
|
62
62
|
const tries = entry.tries || 0;
|
|
63
63
|
const mature = new Date (entry.mature);
|
|
64
64
|
|
|
@@ -73,7 +73,19 @@ class PGQueue extends Queue {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
this._pool.query (`INSERT INTO ${this._tbl_name} VALUES($1, $2, $3, $4)`, [_id, pl, mature, tries], (err, res) => {
|
|
76
|
-
if (err)
|
|
76
|
+
if (err) {
|
|
77
|
+
if (err.code == '23505') {
|
|
78
|
+
const e = new Error (`duplicated entry with _id ${entry._id}`)
|
|
79
|
+
e.code = 'EDUP';
|
|
80
|
+
cb(e)
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
cb (err)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
77
89
|
cb (null, _id)
|
|
78
90
|
})
|
|
79
91
|
}
|
|
@@ -353,7 +365,8 @@ class Factory extends QFactory {
|
|
|
353
365
|
reserve: true,
|
|
354
366
|
pipeline: false,
|
|
355
367
|
tape: false,
|
|
356
|
-
remove: true
|
|
368
|
+
remove: true,
|
|
369
|
+
id: true,
|
|
357
370
|
};
|
|
358
371
|
}
|
|
359
372
|
}
|