@@ -2,8 +2,10 @@ var async = require('async');
2
2
var expect = require ( 'expect.js' ) ;
3
3
var types = require ( '../../lib/types' ) ;
4
4
var deserializedType = require ( './deserialized-type' ) ;
5
+ var numberType = require ( './number-type' ) ;
5
6
types . register ( deserializedType . type ) ;
6
7
types . register ( deserializedType . type2 ) ;
8
+ types . register ( numberType . type ) ;
7
9
8
10
module . exports = function ( ) {
9
11
describe ( 'client submit' , function ( ) {
@@ -509,25 +511,44 @@ describe('client submit', function() {
509
511
} ) ;
510
512
511
513
it ( 'submits fail above the backend.maxSubmitRetries threshold' , function ( done ) {
514
+ var backend = this . backend ;
512
515
this . backend . maxSubmitRetries = 0 ;
513
516
var doc = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
514
517
var doc2 = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
515
518
doc . create ( { age : 3 } , function ( err ) {
516
519
if ( err ) return done ( err ) ;
517
520
doc2 . fetch ( function ( err ) {
518
521
if ( err ) return done ( err ) ;
519
- var count = 0 ;
520
- var cb = function ( err ) {
521
- count ++ ;
522
- if ( count === 1 ) {
523
- if ( err ) return done ( err ) ;
524
- } else {
525
- expect ( err ) . ok ( ) ;
526
- done ( ) ;
522
+ var docCallback ;
523
+ var doc2Callback ;
524
+ // The submit retry happens just after an op is committed. This hook into the middleware
525
+ // catches both ops just before they're about to be committed. This ensures that both ops
526
+ // are certainly working on the same snapshot (ie one op hasn't been committed before the
527
+ // other fetches the snapshot to apply to). By storing the callbacks, we can then
528
+ // manually trigger the callbacks, first calling doc, and when we know that's been committed,
529
+ // we then commit doc2.
530
+ backend . use ( 'commit' , function ( request , callback ) {
531
+ if ( request . op . op [ 0 ] . na === 2 ) docCallback = callback ;
532
+ if ( request . op . op [ 0 ] . na === 7 ) doc2Callback = callback ;
533
+
534
+ // Wait until both ops have been applied to the same snapshot and are about to be committed
535
+ if ( docCallback && doc2Callback ) {
536
+ // Trigger the first op's commit and then the second one later, which will cause the
537
+ // second op to retry
538
+ docCallback ( ) ;
527
539
}
528
- } ;
529
- doc . submitOp ( { p : [ 'age' ] , na : 2 } , cb ) ;
530
- doc2 . submitOp ( { p : [ 'age' ] , na : 7 } , cb ) ;
540
+ } ) ;
541
+ doc . submitOp ( { p : [ 'age' ] , na : 2 } , function ( error ) {
542
+ if ( error ) return done ( error ) ;
543
+ // When we know the first op has been committed, we try to commit the second op, which will
544
+ // fail because it's working on an out-of-date snapshot. It will retry, but exceed the
545
+ // maxSubmitRetries limit of 0
546
+ doc2Callback ( ) ;
547
+ } ) ;
548
+ doc2 . submitOp ( { p : [ 'age' ] , na : 7 } , function ( error ) {
549
+ expect ( error ) . ok ( ) ;
550
+ done ( ) ;
551
+ } ) ;
531
552
} ) ;
532
553
} ) ;
533
554
} ) ;
@@ -608,11 +629,16 @@ describe('client submit', function() {
608
629
doc2 . del ( function ( err ) {
609
630
if ( err ) return done ( err ) ;
610
631
doc . pause ( ) ;
632
+ var calledBack = false ;
633
+ doc . on ( 'error' , function ( ) {
634
+ expect ( calledBack ) . equal ( true ) ;
635
+ done ( ) ;
636
+ } ) ;
611
637
doc . submitOp ( { p : [ 'age' ] , na : 1 } , function ( err ) {
612
638
expect ( err ) . ok ( ) ;
613
639
expect ( doc . version ) . equal ( 2 ) ;
614
640
expect ( doc . data ) . eql ( undefined ) ;
615
- done ( ) ;
641
+ calledBack = true ;
616
642
} ) ;
617
643
doc . fetch ( ) ;
618
644
} ) ;
@@ -632,11 +658,16 @@ describe('client submit', function() {
632
658
doc2 . create ( { age : 5 } , function ( err ) {
633
659
if ( err ) return done ( err ) ;
634
660
doc . pause ( ) ;
661
+ var calledBack = false ;
662
+ doc . on ( 'error' , function ( ) {
663
+ expect ( calledBack ) . equal ( true ) ;
664
+ done ( ) ;
665
+ } ) ;
635
666
doc . create ( { age : 9 } , function ( err ) {
636
667
expect ( err ) . ok ( ) ;
637
668
expect ( doc . version ) . equal ( 3 ) ;
638
669
expect ( doc . data ) . eql ( { age : 5 } ) ;
639
- done ( ) ;
670
+ calledBack = true ;
640
671
} ) ;
641
672
doc . fetch ( ) ;
642
673
} ) ;
@@ -1044,6 +1075,19 @@ describe('client submit', function() {
1044
1075
} ) ;
1045
1076
} ) ;
1046
1077
1078
+ it ( 'allows snapshot and op to be a non-object' , function ( done ) {
1079
+ var doc = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
1080
+ doc . create ( 5 , numberType . type . uri , function ( err ) {
1081
+ if ( err ) return done ( err ) ;
1082
+ expect ( doc . data ) . to . equal ( 5 ) ;
1083
+ doc . submitOp ( 2 , function ( err ) {
1084
+ if ( err ) return done ( err ) ;
1085
+ expect ( doc . data ) . to . equal ( 7 ) ;
1086
+ done ( ) ;
1087
+ } ) ;
1088
+ } ) ;
1089
+ } ) ;
1090
+
1047
1091
describe ( 'type.deserialize' , function ( ) {
1048
1092
it ( 'can create a new doc' , function ( done ) {
1049
1093
var doc = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
0 commit comments