nl_tokens: There are cases where a suitable ancestor in the tree cannot be found or a few docs are missing due to race conditions . To mop these up we make a penultimate pass that considers every unique workflowGuid preferring the locale with the most docs as a basis but falling back if necessary to any in which it exists . And in the final pass we use an aggregation query to find absolutely every last workflowGuid that does not have every locale .
pl_tokens: function fallback ( callback ) { return async . series ( [ viaBasis , noBasis ] , callback ) ; function viaBasis ( callback ) { return self . apos . migrations . eachDoc ( { workflowLocale : basis } , 5 , function ( doc , callback ) { if ( ! self . includeType ( doc . type ) ) { return setImmediate ( callback ) ; } doc . workflowResolveDeferred = true ; var afterSaveOptions = _ . assign ( { } , options , { permissions : false , workflowMissingLocalesLive : self . apos . argv . live ? true : 'liveOnly' } ) ; return self . docAfterSave ( req , doc , afterSaveOptions , callback ) ; } , callback ) ; } function noBasis ( callback ) { var localeNames = Object . keys ( self . locales ) ; var orphans ; return async . series ( [ find , fix ] , callback ) ; function find ( callback ) { const query = [ { $match : { workflowLocale : { $in : localeNames } } } , { $group : { _id : "$workflowGuid" , count : { $sum : 1 } } } , { $match : { count : { $lt : localeNames . length } } } ] ; return self . apos . docs . db . aggregate ( query ) . toArray ( function ( err , _orphans ) { if ( err ) { return callback ( err ) ; } orphans = _orphans ; return callback ( null ) ; } ) ; } function fix ( <mask> ) { var seen = { } ; if ( ! orphans . length ) { return callback ( null ) ; } // The aggregation query returns the workflowGuids but I haven't been able to // convince it to give me representative _ids to go with them, so we will just // ignore the additional locales after we fix each one once. -Tom return self . apos . migrations . eachDoc ( { workflowGuid : { $in : _ . pluck ( orphans , '_id' ) } } , 5 , function ( doc , callback ) { if ( seen [ doc . workflowGuid ] ) { return setImmediate ( callback ) ; } seen [ doc . workflowGuid ] = true ; if ( ! self . includeType ( doc . type ) ) { return setImmediate ( callback ) ; } doc . workflowResolveDeferred = true ; var afterSaveOptions = _ . assign ( { } , options , { permissions : false , workflowMissingLocalesLive : self . apos . argv . live ? true : 'liveOnly' } ) ; return self . docAfterSave ( req , doc , afterSaveOptions , callback ) ; } , callback ) ; } } }