sdk/src/sync/push.js
function pushAllOperations() {
        var currentOperation,
            pushError;
        return readAndLockFirstPendingOperation().then(function(pendingOperation) {
            if (!pendingOperation) {
                return; // No more pending operations. Push is complete
            }
            
            var currentOperation = pendingOperation;
            
            return pushOperation(currentOperation).then(function() {
                return removeLockedOperation();
            }, function(error) {
                // failed to push
                return unlockPendingOperation().then(function() {
                    pushError = createPushError(store, operationTableManager, storeTaskRunner, currentOperation, error);
                    //TODO: If the conflict isn't resolved but the error is marked as handled by the user,
                    //we can end up in an infinite loop. Guard against this by capping the max number of 
                    //times handlePushError can be called for the same record.

                    // We want to reset the retryCount when we move on to the next record
                    if (lastFailedOperationId !== currentOperation.logRecord.id) {
                        lastFailedOperationId = currentOperation.logRecord.id;
                        retryCount = 0;
                    }

                    // Cap the number of times error handling logic is invoked for the same record
                    if (retryCount < maxRetryCount) {
                        ++retryCount;
                        return handlePushError(pushError, pushHandler);
                    }
                });
            }).then(function() {
                if (!pushError) { // no push error
                    lastProcessedOperationId = currentOperation.logRecord.id;
                } else if (pushError && !pushError.isHandled) { // push failed and not handled

                    // For conflict errors, we add the error to the list of errors and continue pushing other records
                    // For other errors, we abort push.
                    if (pushError.isConflict()) {
                        lastProcessedOperationId = currentOperation.logRecord.id;
                        pushConflicts.push(pushError);
                    } else { 
                        throw new verror.VError(pushError.getError(), 'Push failed while pushing operation for tableName : ' + currentOperation.logRecord.tableName +
                                                                 ', action: ' + currentOperation.logRecord.action +
                                                                 ', and record ID: ' + currentOperation.logRecord.itemId);
                    }
                } else { // push error handled
                    // No action needed - We want the operation to be re-pushed.
                    // No special handling is needed even if the operation was cancelled by the user as part of error handling  
                }
            }).then(function() {
                return pushAllOperations(); // push remaining operations
            });
        });
    }
function pushAllOperations() {
        var currentOperation,
            pushError;
        return readAndLockFirstPendingOperation().then(function(pendingOperation) {
            if (!pendingOperation) {
                return; // No more pending operations. Push is complete
            }
            
            var currentOperation = pendingOperation;
            
            return pushOperation(currentOperation).then(function() {
                return removeLockedOperation();
            }, function(error) {
                // failed to push
                return unlockPendingOperation().then(function() {
                    pushError = createPushError(store, operationTableManager, storeTaskRunner, currentOperation, error);
                    //TODO: If the conflict isn't resolved but the error is marked as handled by the user,
                    //we can end up in an infinite loop. Guard against this by capping the max number of 
                    //times handlePushError can be called for the same record.

                    // We want to reset the retryCount when we move on to the next record
                    if (lastFailedOperationId !== currentOperation.logRecord.id) {
                        lastFailedOperationId = currentOperation.logRecord.id;
                        retryCount = 0;
                    }

                    // Cap the number of times error handling logic is invoked for the same record
                    if (retryCount < maxRetryCount) {
                        ++retryCount;
                        return handlePushError(pushError, pushHandler);
                    }
                });
            }).then(function() {
                if (!pushError) { // no push error
                    lastProcessedOperationId = currentOperation.logRecord.id;
                } else if (pushError && !pushError.isHandled) { // push failed and not handled

                    // For conflict errors, we add the error to the list of errors and continue pushing other records
                    // For other errors, we abort push.
                    if (pushError.isConflict()) {
                        lastProcessedOperationId = currentOperation.logRecord.id;
                        pushConflicts.push(pushError);
                    } else { 
                        throw new verror.VError(pushError.getError(), 'Push failed while pushing operation for tableName : ' + currentOperation.logRecord.tableName +
                                                                 ', action: ' + currentOperation.logRecord.action +
                                                                 ', and record ID: ' + currentOperation.logRecord.itemId);
                    }
                } else { // push error handled
                    // No action needed - We want the operation to be re-pushed.
                    // No special handling is needed even if the operation was cancelled by the user as part of error handling  
                }
            }).then(function() {
                return pushAllOperations(); // push remaining operations
            });
        });
    }
function pushAllOperations ( ) { var currentOperation , pushError ; return readAndLockFirstPendingOperation ( ) . then ( function ( pendingOperation ) { if ( ! pendingOperation ) { return ; // No more pending operations. Push is complete } var currentOperation = pendingOperation ; return pushOperation ( currentOperation ) . then ( function ( ) { return removeLockedOperation ( ) ; } , function ( error ) { // failed to push return unlockPendingOperation ( ) . then ( function ( ) { pushError = createPushError ( store , operationTableManager , storeTaskRunner , currentOperation , error ) ; //TODO: If the conflict isn't resolved but the error is marked as handled by the user, //we can end up in an infinite loop. Guard against this by capping the max number of  //times handlePushError can be called for the same record. // We want to reset the retryCount when we move on to the next record if ( lastFailedOperationId !== currentOperation . logRecord . id ) { lastFailedOperationId = currentOperation . logRecord . id ; retryCount = 0 ; } // Cap the number of times error handling logic is invoked for the same record if ( retryCount < maxRetryCount ) { ++ retryCount ; return handlePushError ( pushError , pushHandler ) ; } } ) ; } ) . then ( function ( ) { if ( ! pushError ) { // no push error lastProcessedOperationId = currentOperation . logRecord . id ; } else if ( pushError && ! pushError . isHandled ) { // push failed and not handled // For conflict errors, we add the error to the list of errors and continue pushing other records // For other errors, we abort push. if ( pushError . isConflict ( ) ) { lastProcessedOperationId = currentOperation . logRecord . id ; pushConflicts . push ( pushError ) ; } else { throw new verror . VError ( pushError . getError ( ) , 'Push failed while pushing operation for tableName : ' + currentOperation . logRecord . tableName + ', action: ' + currentOperation . logRecord . action + ', and record ID: ' + currentOperation . logRecord . itemId ) ; } } else { // push error handled // No action needed - We want the operation to be re-pushed. // No special handling is needed even if the operation was cancelled by the user as part of error handling   } } ) . then ( function ( ) { return pushAllOperations ( ) ; // push remaining operations } ) ; } ) ; }
Pushes all pending operations, one at a time. 1. Read the oldest pending operation 2. If 1 did not fetch any operation, go to 6. 3. Lock the operation obtained in step 1 and push it. 4. If 3 is successful, unlock and remove the locked operation from the operation table and go to 1 Else if 3 fails, unlock the operation. 5. If the error is a conflict, handle the conflict and go to 1. 6. Else, EXIT.
Pushes all pending operations one at a time . 1 . Read the oldest pending operation 2 . If 1 did not fetch any operation go to 6 . 3 . Lock the operation obtained in step 1 and push it . 4 . If 3 is successful unlock and remove the locked operation from the operation table and go to 1 Else if 3 fails unlock the operation . 5 . If the error is a conflict handle the conflict and go to 1 . 6 . Else EXIT .