@@ -2,12 +2,74 @@ var util = require('util'),
2
2
Store = require ( '../base' ) ,
3
3
_ = require ( 'lodash' ) ,
4
4
async = require ( 'async' ) ,
5
+ stream = require ( 'stream' ) ,
5
6
mongo = Store . use ( 'mongodb' ) ,
6
7
mongoVersion = Store . use ( 'mongodb/package.json' ) . version ,
7
8
isNew = mongoVersion . indexOf ( '1.' ) !== 0 ,
8
9
ObjectID = isNew ? mongo . ObjectID : mongo . BSONPure . ObjectID ,
9
10
debug = require ( 'debug' ) ( 'eventstore:store:mongodb' ) ;
10
11
12
+ function streamEventsByRevision ( self , findStatement , revMin , revMax , resultStream , lastEvent ) {
13
+
14
+ findStatement . streamRevision = ( revMax === - 1 ) ? { '$gte' : revMin } : { '$gte' : revMin , '$lt' : revMax } ;
15
+
16
+ var mongoStream = self . events . find ( findStatement , { sort : [ [ 'commitStamp' , 'asc' ] , [ 'streamRevision' , 'asc' ] , [ 'commitSequence' , 'asc' ] ] } ) ;
17
+
18
+ async . during ( function ( clb ) {
19
+ mongoStream . hasNext ( clb ) ;
20
+ } ,
21
+ function ( clb ) {
22
+ mongoStream . next ( function ( error , e ) {
23
+ if ( error )
24
+ return clb ( error ) ;
25
+
26
+ if ( ! lastEvent ) {
27
+ lastEvent = e ;
28
+ return clb ( ) ;
29
+ }
30
+
31
+ // if for some reason we have written this event alredy
32
+ if ( ( e . streamRevision === lastEvent . streamRevision && e . restInCommitStream <= lastEvent . restInCommitStream ) ||
33
+ ( e . streamRevision <= lastEvent . streamRevision ) ) {
34
+ return clb ( ) ;
35
+ }
36
+
37
+ lastEvent = e ;
38
+ resultStream . write ( lastEvent , clb ) ;
39
+ } ) ;
40
+ } ,
41
+ function ( error ) {
42
+ if ( error ) {
43
+ return resultStream . destroy ( error ) ;
44
+ }
45
+
46
+ if ( ! lastEvent ) {
47
+ return resultStream . end ( ) ;
48
+ }
49
+
50
+ var txOk = ( revMax === - 1 && ! lastEvent . restInCommitStream ) ||
51
+ ( revMax !== - 1 && ( lastEvent . streamRevision === revMax - 1 || ! lastEvent . restInCommitStream ) ) ;
52
+
53
+ if ( txOk ) {
54
+ // the following is usually unnecessary
55
+ self . removeTransactions ( lastEvent ) ;
56
+ resultStream . end ( lastEvent ) ;
57
+ }
58
+
59
+ self . repairFailedTransaction ( lastEvent , function ( err ) {
60
+ if ( err ) {
61
+ if ( err . message . indexOf ( 'missing tx entry' ) >= 0 ) {
62
+ return resultStream . end ( lastEvent ) ; ;
63
+ }
64
+ debug ( err ) ;
65
+ return resultStream . destroy ( error ) ;
66
+ }
67
+
68
+ streamEventsByRevision ( self , findStatement , lastEvent . revMin , revMax , resultStream , lastEvent ) ;
69
+ } ) ;
70
+ } ) ;
71
+ } ;
72
+
11
73
function Mongo ( options ) {
12
74
options = options || { } ;
13
75
@@ -330,6 +392,33 @@ _.extend(Mongo.prototype, {
330
392
return query ;
331
393
} ,
332
394
395
+ streamEventsByRevision : function ( query , revMin , revMax ) {
396
+ if ( ! query . aggregateId ) {
397
+ var errMsg = 'aggregateId not defined!' ;
398
+ debug ( errMsg ) ;
399
+ if ( callback ) callback ( new Error ( errMsg ) ) ;
400
+ return ;
401
+ }
402
+
403
+ var findStatement = {
404
+ aggregateId : query . aggregateId ,
405
+ } ;
406
+
407
+ if ( query . aggregate ) {
408
+ findStatement . aggregate = query . aggregate ;
409
+ }
410
+
411
+ if ( query . context ) {
412
+ findStatement . context = query . context ;
413
+ }
414
+
415
+ var self = this ;
416
+
417
+ var resultStream = new stream . PassThrough ( { objectMode : true , highWaterMark : 1 } ) ;
418
+ streamEventsByRevision ( self , findStatement , revMin , revMax , resultStream ) ;
419
+ return resultStream ;
420
+ } ,
421
+
333
422
getEvents : function ( query , skip , limit , callback ) {
334
423
this . streamEvents ( query , skip , limit ) . toArray ( callback ) ;
335
424
} ,
0 commit comments