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
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const async = require ('async');
|
|
2
|
+
const _ = require ('lodash');
|
|
3
|
+
const AsyncLock = require ('async-lock');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const debug = require('debug')('keuss:backend:BucketMongoSafe');
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const MongoClient = require ('mongodb').MongoClient;
|
|
9
|
+
const mongo = require ('mongodb');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const Queue = require ('../Queue');
|
|
12
|
+
const QFactory_MongoDB_defaults = require ('../QFactory-MongoDB-defaults');
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const State = {
|
|
15
15
|
Available: 1,
|
|
16
16
|
Reserved: 2,
|
|
17
17
|
Committed: 3,
|
|
@@ -79,9 +79,9 @@ class Bucket {
|
|
|
79
79
|
|
|
80
80
|
debug ('Bucket:got_element: look for next available elem starting at pos %d', this._last_b_idx);
|
|
81
81
|
|
|
82
|
-
for (
|
|
82
|
+
for (let i = this._last_b_idx; i < this._b_states.length; i++) {
|
|
83
83
|
if (this._b_states[i] == State.Available) {
|
|
84
|
-
|
|
84
|
+
const elem = {};
|
|
85
85
|
if (this._b[i].__p) {
|
|
86
86
|
// add-headers: array contains both payload and headers, breaks backwards compat
|
|
87
87
|
elem.payload = this._b[i].__p;
|
|
@@ -121,16 +121,11 @@ class Bucket {
|
|
|
121
121
|
|
|
122
122
|
/////////////////////////////////////////
|
|
123
123
|
_flush_delete_bucket (cb) {
|
|
124
|
-
|
|
124
|
+
const q = {_id: this._id};
|
|
125
125
|
debug ('Bucket: deleting whole bucket %o', q);
|
|
126
126
|
|
|
127
|
-
this._col.deleteOne (q
|
|
128
|
-
|
|
129
|
-
err: 'Bucket flush: mongodb error',
|
|
130
|
-
e: err,
|
|
131
|
-
q: q
|
|
132
|
-
});
|
|
133
|
-
|
|
127
|
+
this._col.deleteOne (q)
|
|
128
|
+
.then (res => {
|
|
134
129
|
if ((res && res.deletedCount) != 1) {
|
|
135
130
|
return cb({
|
|
136
131
|
err: 'Bucket flush: exactly one must be deleted',
|
|
@@ -141,23 +136,30 @@ class Bucket {
|
|
|
141
136
|
|
|
142
137
|
debug ('Bucket: deleted whole bucket %o', q);
|
|
143
138
|
cb (null, null);
|
|
144
|
-
})
|
|
139
|
+
})
|
|
140
|
+
.catch (err => {
|
|
141
|
+
cb({
|
|
142
|
+
err: 'Bucket flush: mongodb error',
|
|
143
|
+
e: err,
|
|
144
|
+
q: q
|
|
145
|
+
});
|
|
146
|
+
})
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
|
|
148
150
|
/////////////////////////////////////////
|
|
149
151
|
_flush_bucket (cb) {
|
|
150
|
-
|
|
152
|
+
const upd = {
|
|
151
153
|
$set: {}
|
|
152
154
|
};
|
|
153
155
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
let has_update = false;
|
|
157
|
+
const committed_pos = [];
|
|
158
|
+
let mature = null;
|
|
159
|
+
let timed_out = false;
|
|
160
|
+
let is_reject = false;
|
|
159
161
|
|
|
160
|
-
|
|
162
|
+
const time_left = this._mature_t - new Date().getTime();
|
|
161
163
|
debug ('time left is %d, grace is %d', time_left, this._reject_timeout_grace);
|
|
162
164
|
|
|
163
165
|
if (time_left < this._reject_timeout_grace) {
|
|
@@ -189,13 +191,13 @@ class Bucket {
|
|
|
189
191
|
) {
|
|
190
192
|
debug ('Bucket: flushing entire bucket for retry (%o)', this._b_counts);
|
|
191
193
|
is_reject = true;
|
|
192
|
-
|
|
194
|
+
const tries = this._tries || 0;
|
|
193
195
|
|
|
194
196
|
if (this._rollback_next_t) {
|
|
195
197
|
mature = new Date (this._rollback_next_t);
|
|
196
198
|
}
|
|
197
199
|
else {
|
|
198
|
-
|
|
200
|
+
const delta = this._reject_delta_factor * tries + this._reject_delta_base;
|
|
199
201
|
mature = new Date (new Date().getTime () + delta)
|
|
200
202
|
}
|
|
201
203
|
|
|
@@ -205,17 +207,12 @@ class Bucket {
|
|
|
205
207
|
}
|
|
206
208
|
|
|
207
209
|
if (has_update) {
|
|
208
|
-
|
|
210
|
+
const q = {_id: this._id};
|
|
209
211
|
|
|
210
212
|
debug ('update on bucket: q is %o, upd is %o', q, upd);
|
|
211
213
|
|
|
212
|
-
this._col.updateOne (q, upd
|
|
213
|
-
|
|
214
|
-
err: 'Bucket flush: mongodb error',
|
|
215
|
-
e: err,
|
|
216
|
-
q: q
|
|
217
|
-
});
|
|
218
|
-
|
|
214
|
+
this._col.updateOne (q, upd)
|
|
215
|
+
.then (res => {
|
|
219
216
|
if (res && (res.modifiedCount != 1)) return cb({
|
|
220
217
|
err: 'Bucket flush: exactly one must be updated',
|
|
221
218
|
e: err,
|
|
@@ -234,7 +231,14 @@ class Bucket {
|
|
|
234
231
|
|
|
235
232
|
debug ('Bucket: flushed ok, states are %o (%o)', this._b_states, this._b_counts);
|
|
236
233
|
cb (null, is_reject ? null : this._b_counts);
|
|
237
|
-
})
|
|
234
|
+
})
|
|
235
|
+
.catch (err => {
|
|
236
|
+
cb({
|
|
237
|
+
err: 'Bucket flush: mongodb error',
|
|
238
|
+
e: err,
|
|
239
|
+
q: q
|
|
240
|
+
});
|
|
241
|
+
})
|
|
238
242
|
}
|
|
239
243
|
else {
|
|
240
244
|
debug ('Bucket: nothing to flush');
|
|
@@ -279,11 +283,11 @@ class BucketSet {
|
|
|
279
283
|
|
|
280
284
|
///////////////////////////////
|
|
281
285
|
_read_bucket (cb) {
|
|
282
|
-
|
|
286
|
+
const query = {
|
|
283
287
|
mature: {$lte: Queue.now ()}
|
|
284
288
|
};
|
|
285
289
|
|
|
286
|
-
|
|
290
|
+
const update = {
|
|
287
291
|
$set: {
|
|
288
292
|
mature: Queue.nowPlusSecs (this._reserve_delay),
|
|
289
293
|
reserved: new Date ()
|
|
@@ -291,21 +295,21 @@ class BucketSet {
|
|
|
291
295
|
$inc: {tries: 1}
|
|
292
296
|
};
|
|
293
297
|
|
|
294
|
-
|
|
298
|
+
const opts = {
|
|
295
299
|
sort: {mature : 1},
|
|
296
|
-
returnDocument: 'after'
|
|
300
|
+
returnDocument: 'after',
|
|
301
|
+
includeResultMetadata: true
|
|
297
302
|
};
|
|
298
303
|
|
|
299
304
|
debug ('reading a new bucket');
|
|
300
305
|
|
|
301
|
-
this._col.findOneAndUpdate (query, update, opts
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
var val = result && result.value;
|
|
306
|
+
this._col.findOneAndUpdate (query, update, opts)
|
|
307
|
+
.then (res => {
|
|
308
|
+
const val = res && res.value;
|
|
305
309
|
|
|
306
310
|
if (val) {
|
|
307
311
|
debug ('read a bucket %s with %d elems', val._id.toString(), val.n);
|
|
308
|
-
|
|
312
|
+
const bcket = new Bucket (val, this._col, this._q, this._opts);
|
|
309
313
|
this._buckets[bcket.id()] = bcket;
|
|
310
314
|
|
|
311
315
|
// is already exhausted?
|
|
@@ -323,7 +327,8 @@ class BucketSet {
|
|
|
323
327
|
debug ('no buckets, coll empty');
|
|
324
328
|
cb ();
|
|
325
329
|
}
|
|
326
|
-
})
|
|
330
|
+
})
|
|
331
|
+
.catch (cb)
|
|
327
332
|
}
|
|
328
333
|
|
|
329
334
|
|
|
@@ -377,7 +382,7 @@ class BucketSet {
|
|
|
377
382
|
return cb (); // coll empty or not mature
|
|
378
383
|
}
|
|
379
384
|
|
|
380
|
-
|
|
385
|
+
const elem = this._active_bucket.get_element (is_reserve);
|
|
381
386
|
|
|
382
387
|
if (!elem) {
|
|
383
388
|
debug ('BucketSet:getElement: active bucket exhausted, get another');
|
|
@@ -406,11 +411,11 @@ class BucketSet {
|
|
|
406
411
|
|
|
407
412
|
/////////////////////////////
|
|
408
413
|
commit_element (id, cb) {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
414
|
+
const aid = id.split (':');
|
|
415
|
+
const bucket_id = aid[0];
|
|
416
|
+
const bucket_idx = parseInt(aid[1]);
|
|
412
417
|
|
|
413
|
-
|
|
418
|
+
const bucket = this._buckets[bucket_id];
|
|
414
419
|
if (!bucket) return cb (null, false);
|
|
415
420
|
if (bucket._b_states[bucket_idx] != State.Reserved) return cb (null, false);
|
|
416
421
|
|
|
@@ -425,11 +430,11 @@ class BucketSet {
|
|
|
425
430
|
|
|
426
431
|
/////////////////////////////
|
|
427
432
|
rollback_element (id, next_t, cb) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
433
|
+
const aid = id.split (':');
|
|
434
|
+
const bucket_id = aid[0];
|
|
435
|
+
const bucket_idx = parseInt(aid[1]);
|
|
431
436
|
|
|
432
|
-
|
|
437
|
+
const bucket = this._buckets[bucket_id];
|
|
433
438
|
if (!bucket) return cb (null, false);
|
|
434
439
|
if (bucket._b_states[bucket_idx] != State.Reserved) return cb (null, false);
|
|
435
440
|
|
|
@@ -451,7 +456,7 @@ class BucketSet {
|
|
|
451
456
|
|
|
452
457
|
debug ('BucketSet:_flush_state_changes: tick');
|
|
453
458
|
|
|
454
|
-
|
|
459
|
+
const tasks = {};
|
|
455
460
|
_.each (this._buckets, (bucket, id) => {
|
|
456
461
|
tasks[id] = (cb) => {
|
|
457
462
|
debug ('BucketSet:_flush_state_changes: flushing bucket %s', bucket.id());
|
|
@@ -517,7 +522,6 @@ class BucketSet {
|
|
|
517
522
|
}
|
|
518
523
|
|
|
519
524
|
|
|
520
|
-
|
|
521
525
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
522
526
|
class BucketMongoSafeQueue extends Queue {
|
|
523
527
|
/*
|
|
@@ -532,13 +536,12 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
532
536
|
*/
|
|
533
537
|
//////////////////////////////////////////////
|
|
534
538
|
constructor (name, factory, opts, orig_opts) {
|
|
535
|
-
//////////////////////////////////////////////
|
|
536
539
|
super (name, factory, opts, orig_opts);
|
|
537
540
|
|
|
538
541
|
this._col = factory._db.collection (name);
|
|
539
542
|
|
|
540
543
|
this._insert_bucket = {
|
|
541
|
-
_id: new mongo.
|
|
544
|
+
_id: new mongo.ObjectId (),
|
|
542
545
|
b: []
|
|
543
546
|
};
|
|
544
547
|
|
|
@@ -553,21 +556,18 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
553
556
|
|
|
554
557
|
/////////////////////////////////////////
|
|
555
558
|
static Type () {
|
|
556
|
-
/////////////////////////////////////////
|
|
557
559
|
return 'mongo:bucket-safe';
|
|
558
560
|
}
|
|
559
561
|
|
|
560
562
|
/////////////////////////////////////////
|
|
561
563
|
type () {
|
|
562
|
-
/////////////////////////////////////////
|
|
563
564
|
return 'mongo:bucket-safe';
|
|
564
565
|
}
|
|
565
566
|
|
|
566
567
|
|
|
567
568
|
/////////////////////////////////////////
|
|
568
569
|
// add element to queue
|
|
569
|
-
insert (entry,
|
|
570
|
-
/////////////////////////////////////////
|
|
570
|
+
insert (entry, cb) {
|
|
571
571
|
if (!this._insert_bucket.mature) this._insert_bucket.mature = entry.mature;
|
|
572
572
|
else if (this._insert_bucket.mature.getTime () < entry.mature.getTime ()) this._insert_bucket.mature = entry.mature;
|
|
573
573
|
|
|
@@ -576,7 +576,7 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
576
576
|
__h: (entry.hdrs || {})
|
|
577
577
|
});
|
|
578
578
|
|
|
579
|
-
|
|
579
|
+
const id = this._insert_bucket._id.toString () + ':' + (this._insert_bucket.b.length - 1);
|
|
580
580
|
debug ('added to bucket, %s', id);
|
|
581
581
|
|
|
582
582
|
if (this._insert_bucket.b.length >= this._bucket_max_size) {
|
|
@@ -585,7 +585,7 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
585
585
|
|
|
586
586
|
debug ('cancelled periodic_flush');
|
|
587
587
|
|
|
588
|
-
this._flush_bucket (
|
|
588
|
+
this._flush_bucket (cb);
|
|
589
589
|
}
|
|
590
590
|
else {
|
|
591
591
|
if (this._insert_bucket.b.length == 1) {
|
|
@@ -593,91 +593,95 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
593
593
|
this._set_periodic_flush ();
|
|
594
594
|
}
|
|
595
595
|
|
|
596
|
-
setImmediate (() =>
|
|
596
|
+
setImmediate (() => cb (null, id));
|
|
597
597
|
}
|
|
598
598
|
}
|
|
599
599
|
|
|
600
600
|
|
|
601
601
|
/////////////////////////////////////////
|
|
602
602
|
// get element from queue
|
|
603
|
-
get (
|
|
603
|
+
get (cb) {
|
|
604
604
|
this._read_bucket.get_element ((err, elem) => {
|
|
605
|
-
if (err) return
|
|
605
|
+
if (err) return cb (err);
|
|
606
606
|
if (elem && elem.payload._bsontype == 'Binary') elem.payload = elem.payload.buffer;
|
|
607
607
|
if (elem && elem.tries > 0) elem.tries--;
|
|
608
|
-
|
|
608
|
+
cb (null, elem);
|
|
609
609
|
});
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
|
|
613
613
|
/////////////////////////////////////////
|
|
614
614
|
// reserve element from queue
|
|
615
|
-
reserve (
|
|
615
|
+
reserve (cb) {
|
|
616
616
|
this._read_bucket.reserve_element ((err, elem) => {
|
|
617
|
-
if (err) return
|
|
617
|
+
if (err) return cb (err);
|
|
618
618
|
if (elem && elem.payload._bsontype == 'Binary') elem.payload = elem.payload.buffer;
|
|
619
619
|
if (elem && elem.tries > 0) elem.tries--;
|
|
620
|
-
|
|
620
|
+
cb (null, elem);
|
|
621
621
|
});
|
|
622
622
|
}
|
|
623
623
|
|
|
624
624
|
|
|
625
625
|
/////////////////////////////////////////
|
|
626
626
|
// commit a reserved element from queue
|
|
627
|
-
commit (id,
|
|
627
|
+
commit (id, cb) {
|
|
628
628
|
this._read_bucket.commit_element (id, (err, elem) => {
|
|
629
|
-
if (err) return
|
|
630
|
-
|
|
629
|
+
if (err) return cb (err);
|
|
630
|
+
cb (null, elem);
|
|
631
631
|
});
|
|
632
632
|
}
|
|
633
633
|
|
|
634
634
|
|
|
635
635
|
/////////////////////////////////////////
|
|
636
636
|
// rollback a reserved element from queue
|
|
637
|
-
rollback (id, next_t,
|
|
637
|
+
rollback (id, next_t, cb) {
|
|
638
638
|
this._read_bucket.rollback_element (id, next_t, (err, elem) => {
|
|
639
|
-
if (err) return
|
|
640
|
-
|
|
639
|
+
if (err) return cb (err);
|
|
640
|
+
cb (null, elem);
|
|
641
641
|
});
|
|
642
642
|
}
|
|
643
643
|
|
|
644
644
|
|
|
645
645
|
//////////////////////////////////
|
|
646
646
|
// queue size including non-mature elements
|
|
647
|
-
totalSize (
|
|
647
|
+
totalSize (cb) {
|
|
648
648
|
const cursor = this._col.aggregate ([
|
|
649
649
|
{$group:{_id:'t', v: {$sum: '$n'}}}
|
|
650
650
|
]);
|
|
651
651
|
|
|
652
|
-
cursor
|
|
652
|
+
cursor
|
|
653
|
+
.toArray ()
|
|
654
|
+
.then (res => {
|
|
653
655
|
debug ('calculating totalSize: aggregation pipeline returns %o', res);
|
|
654
|
-
if (
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
656
|
+
if (res.length == 0) return cb (null, 0);
|
|
657
|
+
cb (null, res[0].v);
|
|
658
|
+
})
|
|
659
|
+
.catch (cb);
|
|
658
660
|
}
|
|
659
661
|
|
|
660
662
|
|
|
661
663
|
//////////////////////////////////
|
|
662
664
|
// queue size NOT including non-mature elements
|
|
663
|
-
size (
|
|
665
|
+
size (cb) {
|
|
664
666
|
const cursor = this._col.aggregate ([
|
|
665
667
|
{$match: {mature: {$lte: Queue.now ()}}},
|
|
666
668
|
{$group:{_id:'t', v: {$sum: '$n'}}}
|
|
667
669
|
]);
|
|
668
670
|
|
|
669
|
-
cursor
|
|
671
|
+
cursor
|
|
672
|
+
.toArray ()
|
|
673
|
+
.then (res => {
|
|
670
674
|
debug ('calculating size: aggregation pipeline returns %o', res);
|
|
671
|
-
if (
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
+
if (res.length == 0) return cb (null, 0);
|
|
676
|
+
cb (null, res[0].v);
|
|
677
|
+
})
|
|
678
|
+
.catch (cb);
|
|
675
679
|
}
|
|
676
680
|
|
|
677
681
|
|
|
678
682
|
//////////////////////////////////
|
|
679
683
|
// queue size of non-mature elements only
|
|
680
|
-
schedSize (
|
|
684
|
+
schedSize (cb) {
|
|
681
685
|
const cursor = this._col.aggregate ([
|
|
682
686
|
{$match: {
|
|
683
687
|
mature: {$gt: Queue.now ()},
|
|
@@ -686,18 +690,20 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
686
690
|
{$group:{_id:'t', v: {$sum: '$n'}}}
|
|
687
691
|
]);
|
|
688
692
|
|
|
689
|
-
cursor
|
|
693
|
+
cursor
|
|
694
|
+
.toArray ()
|
|
695
|
+
.then (res => {
|
|
690
696
|
debug ('calculating schedSize: aggregation pipeline returns %o', res);
|
|
691
|
-
if (
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
697
|
+
if (res.length == 0) return cb (null, 0);
|
|
698
|
+
cb (null, res[0].v);
|
|
699
|
+
})
|
|
700
|
+
.catch (cb);
|
|
695
701
|
}
|
|
696
702
|
|
|
697
703
|
|
|
698
704
|
//////////////////////////////////
|
|
699
705
|
// queue size of non-mature elements only
|
|
700
|
-
resvSize (
|
|
706
|
+
resvSize (cb) {
|
|
701
707
|
const cursor = this._col.aggregate ([
|
|
702
708
|
{$match: {
|
|
703
709
|
mature: {$gt: Queue.now ()},
|
|
@@ -706,50 +712,55 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
706
712
|
{$group:{_id:'t', v: {$sum: '$n'}}}
|
|
707
713
|
]);
|
|
708
714
|
|
|
709
|
-
cursor
|
|
715
|
+
cursor
|
|
716
|
+
.toArray ()
|
|
717
|
+
.then (res => {
|
|
710
718
|
debug ('calculating resvSize: aggregation pipeline returns %o', res);
|
|
711
|
-
if (
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
719
|
+
if (res.length == 0) return cb (null, 0);
|
|
720
|
+
cb (null, res[0].v);
|
|
721
|
+
})
|
|
722
|
+
.catch (cb);
|
|
715
723
|
}
|
|
716
724
|
|
|
717
725
|
|
|
718
726
|
/////////////////////////////////////////
|
|
719
727
|
// get element from queue
|
|
720
|
-
next_t (
|
|
728
|
+
next_t (cb) {
|
|
721
729
|
this._col.findOne ({}, {
|
|
722
730
|
sort: {mature:1},
|
|
723
731
|
projection: {mature: 1}
|
|
724
|
-
}
|
|
725
|
-
(
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
732
|
+
})
|
|
733
|
+
.then (res => {
|
|
734
|
+
debug ('obtaining next_t: got %o', res && res.mature);
|
|
735
|
+
cb (null, res && res.mature);
|
|
736
|
+
})
|
|
737
|
+
.catch (cb);
|
|
730
738
|
}
|
|
731
739
|
|
|
732
740
|
|
|
733
741
|
//////////////////////////////////////////////
|
|
734
742
|
// remove by id
|
|
735
|
-
remove (id,
|
|
743
|
+
remove (id, cb) {
|
|
744
|
+
let bucket_id;
|
|
745
|
+
const aid = id.split (':');
|
|
746
|
+
|
|
736
747
|
try {
|
|
737
|
-
|
|
738
|
-
var bucket_id = new mongo.ObjectID (aid[0]);
|
|
739
|
-
var bucket_idx = parseInt(aid[1]);
|
|
748
|
+
bucket_id = new mongo.ObjectId (aid[0]);
|
|
740
749
|
}
|
|
741
750
|
catch (e) {
|
|
742
|
-
return
|
|
751
|
+
return cb ('id [' + id + '] can not be used as remove id: ' + e);
|
|
743
752
|
}
|
|
753
|
+
|
|
754
|
+
const bucket_idx = parseInt(aid[1]);
|
|
744
755
|
|
|
745
|
-
|
|
756
|
+
const upd = {
|
|
746
757
|
$set: {},
|
|
747
758
|
$inc: {n: -1}
|
|
748
759
|
};
|
|
749
760
|
|
|
750
761
|
upd.$set['b.' + bucket_idx] = null;
|
|
751
762
|
|
|
752
|
-
|
|
763
|
+
const q = {
|
|
753
764
|
_id: bucket_id,
|
|
754
765
|
reserved: {$exists: false},
|
|
755
766
|
};
|
|
@@ -757,10 +768,9 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
757
768
|
q['b.' + bucket_idx] = {$type: 3}; // b.N is an object
|
|
758
769
|
|
|
759
770
|
debug ('update on bucket: q is %o, upd is %o', q, upd);
|
|
760
|
-
this._col.updateOne (q, upd
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
});
|
|
771
|
+
this._col.updateOne (q, upd)
|
|
772
|
+
.then (res => cb (null, res && (res.modifiedCount == 1)))
|
|
773
|
+
.catch (cb);
|
|
764
774
|
}
|
|
765
775
|
|
|
766
776
|
|
|
@@ -814,7 +824,9 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
814
824
|
|
|
815
825
|
/////////////////////////////////////////
|
|
816
826
|
_ensureIndexes (cb) {
|
|
817
|
-
this._col.createIndex ({mature : 1}
|
|
827
|
+
this._col.createIndex ({mature : 1})
|
|
828
|
+
.then (res => cb (null, this))
|
|
829
|
+
.catch (cb);
|
|
818
830
|
}
|
|
819
831
|
|
|
820
832
|
|
|
@@ -846,44 +858,44 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
846
858
|
|
|
847
859
|
|
|
848
860
|
/////////////////////////////////////////
|
|
849
|
-
_flush_bucket (
|
|
861
|
+
_flush_bucket (cb) {
|
|
850
862
|
/////////////////////////////////////////
|
|
851
|
-
|
|
863
|
+
const bucket = this._insert_bucket;
|
|
852
864
|
bucket.n = bucket.b.length;
|
|
853
865
|
|
|
854
866
|
this._insert_bucket = {
|
|
855
|
-
_id: new mongo.
|
|
867
|
+
_id: new mongo.ObjectId (),
|
|
856
868
|
b: []
|
|
857
869
|
};
|
|
858
870
|
|
|
859
871
|
debug ('flushing bucket %s with %d elems', bucket._id.toString(), bucket.b.length);
|
|
860
872
|
|
|
861
|
-
this._col.insertOne (bucket, {}
|
|
862
|
-
|
|
863
|
-
|
|
873
|
+
this._col.insertOne (bucket, {})
|
|
874
|
+
.then (res => {
|
|
864
875
|
this._signal_insertion_own (bucket.mature);
|
|
865
|
-
|
|
866
|
-
})
|
|
876
|
+
cb (null, bucket);
|
|
877
|
+
})
|
|
878
|
+
.catch (cb);
|
|
867
879
|
}
|
|
868
880
|
|
|
869
881
|
|
|
870
882
|
/////////////////////////////////////////
|
|
871
883
|
// get element from queue
|
|
872
|
-
_get_bucket (
|
|
884
|
+
_get_bucket (cb) {
|
|
873
885
|
/////////////////////////////////////////
|
|
874
886
|
debug ('need to read a bucket');
|
|
875
887
|
|
|
876
|
-
this._col.findOneAndDelete ({}, {sort: {_id : 1}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
var val = result && result.value;
|
|
888
|
+
this._col.findOneAndDelete ({}, {sort: {_id : 1}, includeResultMetadata: true})
|
|
889
|
+
.then (res => {
|
|
890
|
+
const val = res && res.value;
|
|
880
891
|
|
|
881
892
|
if (val) {
|
|
882
893
|
debug ('read a bucket %s with %d elems', val._id.toString(), val.n);
|
|
883
894
|
}
|
|
884
895
|
|
|
885
|
-
|
|
886
|
-
})
|
|
896
|
+
cb (null, val);
|
|
897
|
+
})
|
|
898
|
+
.catch (cb);
|
|
887
899
|
}
|
|
888
900
|
|
|
889
901
|
|
|
@@ -901,6 +913,7 @@ class BucketMongoSafeQueue extends Queue {
|
|
|
901
913
|
};
|
|
902
914
|
|
|
903
915
|
|
|
916
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
904
917
|
class Factory extends QFactory_MongoDB_defaults {
|
|
905
918
|
constructor (opts, mongo_conn) {
|
|
906
919
|
super (opts);
|
|
@@ -908,6 +921,7 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
908
921
|
this._db = mongo_conn.db();
|
|
909
922
|
}
|
|
910
923
|
|
|
924
|
+
////////////////////////////////////////
|
|
911
925
|
queue (name, opts, cb) {
|
|
912
926
|
if (!cb) {
|
|
913
927
|
cb = opts;
|
|
@@ -921,6 +935,7 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
921
935
|
q._ensureIndexes (cb);
|
|
922
936
|
}
|
|
923
937
|
|
|
938
|
+
////////////////////////////////////////
|
|
924
939
|
close (cb) {
|
|
925
940
|
super.close (() => {
|
|
926
941
|
if (this._mongo_conn) {
|
|
@@ -932,30 +947,36 @@ class Factory extends QFactory_MongoDB_defaults {
|
|
|
932
947
|
});
|
|
933
948
|
}
|
|
934
949
|
|
|
950
|
+
////////////////////////////////////////
|
|
935
951
|
type () {
|
|
936
952
|
return BucketMongoSafeQueue.Type ();
|
|
937
953
|
}
|
|
938
954
|
|
|
955
|
+
////////////////////////////////////////
|
|
939
956
|
capabilities () {
|
|
940
957
|
return {
|
|
941
958
|
sched: true,
|
|
942
959
|
reserve: true,
|
|
943
960
|
pipeline: false,
|
|
944
961
|
tape: false,
|
|
945
|
-
remove: true
|
|
962
|
+
remove: true,
|
|
963
|
+
id: false,
|
|
946
964
|
};
|
|
947
965
|
}
|
|
948
966
|
}
|
|
949
967
|
|
|
968
|
+
|
|
969
|
+
////////////////////////////////////////
|
|
950
970
|
function creator (opts, cb) {
|
|
951
|
-
|
|
952
|
-
|
|
971
|
+
const _opts = opts || {};
|
|
972
|
+
const m_url = _opts.url || 'mongodb://localhost:27017/keuss';
|
|
953
973
|
|
|
954
|
-
MongoClient.connect (m_url
|
|
955
|
-
|
|
956
|
-
|
|
974
|
+
MongoClient.connect (m_url)
|
|
975
|
+
.then (cl => {
|
|
976
|
+
const F = new Factory (_opts, cl);
|
|
957
977
|
F.async_init (err => cb (null, F));
|
|
958
|
-
})
|
|
978
|
+
})
|
|
979
|
+
.catch (cb);
|
|
959
980
|
}
|
|
960
981
|
|
|
961
982
|
module.exports = creator;
|