lib/pending-processor.js
function doDelete(datasetId, pendingChange, callback) {
  debug('[%s] DELETE Start', datasetId);
  var metaData = pendingChange.meta_data;
  var uid = pendingChange.uid;
  dataHandlers.doRead(datasetId, uid, metaData, function(err, data) {
    if (err) {
      debugError('READ for DELETE Failed - uid = %s : err = %s', datasetId, uid, err);
      return saveUpdate(datasetId, pendingChange, SYNC_UPDATE_TYPES.FAILED, util.inspect(err), callback);
    }
    debug('[%s] READ for DELETE Success', datasetId);
    debug('[%s] READ for DELETE Data : \n%j', datasetId, data);

    var preHash = hashProvider.recordHash(datasetId, pendingChange.pre);
    var dataHash = hashProvider.recordHash(datasetId, data);

    debug('[%s] DELETE Hash Check %s (client :: dataStore) = %s :: %s', datasetId, uid, preHash.dataHash);

    if (!dataHash) {
      //record has already been deleted
      debug('[%s] DELETE Already performed - uid=%s', datasetId, uid);
      return saveUpdate(datasetId, pendingChange, SYNC_UPDATE_TYPES.APPLIED, null, callback);
    }
    else {
      if (preHash === dataHash) {
        dataHandlers.doDelete(datasetId, uid, metaData, function(err) {
          if (err) {
            debugError('[%s] DELETE Failed - uid=%s : err = %s', datasetId, err);
          } else {
            debug('[%s] DELETE Success - uid=%s : hash = %s', datasetId, dataHash);
          }
          return saveUpdate(datasetId, pendingChange, err ? SYNC_UPDATE_TYPES.FAILED : SYNC_UPDATE_TYPES.APPLIED, err ? util.inspect(err) : null, callback);
        });
      } else {
        debug('[%s] DELETE COLLISION \n Pre record from client:\n%j\nCurrent record from data store:\n%j', datasetId, syncUtil.sortObject(pendingChange.pre), syncUtil.sortObject(data));
        handleCollision(datasetId, metaData, pendingChange, dataHash, function(err) {
          if (err) {
            debugError('[%s] Failed to save collision uid = %s : err = %s', datasetId, err);
          }
        });
        return saveUpdate(datasetId, pendingChange, SYNC_UPDATE_TYPES.COLLISION, null, callback);
      }
    }
  });
}
function doDelete(datasetId, pendingChange, callback) {
  debug('[%s] DELETE Start', datasetId);
  var metaData = pendingChange.meta_data;
  var uid = pendingChange.uid;
  dataHandlers.doRead(datasetId, uid, metaData, function(err, data) {
    if (err) {
      debugError('READ for DELETE Failed - uid = %s : err = %s', datasetId, uid, err);
      return saveUpdate(datasetId, pendingChange, SYNC_UPDATE_TYPES.FAILED, util.inspect(err), callback);
    }
    debug('[%s] READ for DELETE Success', datasetId);
    debug('[%s] READ for DELETE Data : \n%j', datasetId, data);

    var preHash = hashProvider.recordHash(datasetId, pendingChange.pre);
    var dataHash = hashProvider.recordHash(datasetId, data);

    debug('[%s] DELETE Hash Check %s (client :: dataStore) = %s :: %s', datasetId, uid, preHash.dataHash);

    if (!dataHash) {
      //record has already been deleted
      debug('[%s] DELETE Already performed - uid=%s', datasetId, uid);
      return saveUpdate(datasetId, pendingChange, SYNC_UPDATE_TYPES.APPLIED, null, callback);
    }
    else {
      if (preHash === dataHash) {
        dataHandlers.doDelete(datasetId, uid, metaData, function(err) {
          if (err) {
            debugError('[%s] DELETE Failed - uid=%s : err = %s', datasetId, err);
          } else {
            debug('[%s] DELETE Success - uid=%s : hash = %s', datasetId, dataHash);
          }
          return saveUpdate(datasetId, pendingChange, err ? SYNC_UPDATE_TYPES.FAILED : SYNC_UPDATE_TYPES.APPLIED, err ? util.inspect(err) : null, callback);
        });
      } else {
        debug('[%s] DELETE COLLISION \n Pre record from client:\n%j\nCurrent record from data store:\n%j', datasetId, syncUtil.sortObject(pendingChange.pre), syncUtil.sortObject(data));
        handleCollision(datasetId, metaData, pendingChange, dataHash, function(err) {
          if (err) {
            debugError('[%s] Failed to save collision uid = %s : err = %s', datasetId, err);
          }
        });
        return saveUpdate(datasetId, pendingChange, SYNC_UPDATE_TYPES.COLLISION, null, callback);
      }
    }
  });
}
Delete the given pending change from the backend.
It will only delete the record if the hash value of the `pre` record matches the hash value of the record from backend.
Otherwise the change is either already applied, or a collision will be generated.
@param {String} datasetId the dataset id
@param {Object} pendingChange the pending change. It should have the following fields
@param {String} pendingChange.datasetId the dataset id of the pending change
@param {Object} pendingChange.meta_data the meta_data of the dataset
@param {String} pendingChange.action the action of the pending change, should be "delete"
@param {String} pendingChange.uid the unique id of the data record
@param {String} pendingChange.cuid the unique client id of the client device
@param {String} pendingChange.hash a unique id of the pending change, normally it is a hash value generated from the content of the pendingChange object
@param {Object} pendingChange.pre the record before change.
@param {Function} callback