<commit_before>function SmartCollection(name) {
  var self = this;
  this.name = name;
  this._remoteCollection = new Meteor.Collection(name);
  this._localCollection = new Meteor.Collection(null);

  this._pipeHandler = this._pipe(this._remoteCollection, this._localCollection);

  //wrap methods from the _remoteCollection
  ['find', 'findOne', 'allow', 'deny'].forEach(function(field) {
    self[field] = function() {
      return self._localCollection[field].apply(self._localCollection, arguments);
    };
  });
}

SmartCollection.prototype.insert = function(doc, callback) {
  //_si_ == smart insert :P
  if(!doc._id) {
    doc._id = Random.id();
  }

  if(this._isSimulation()) {
    this._remoteCollection.insert(doc, callback);
  } else {
    Meteor.call('_si_', this.name, doc, callback);
  }
  return doc._id;
};

SmartCollection.prototype.update = function(selector, modifier, callback) {
  if(this._isSimulation()) {
    this._remoteCollection.update(selector, modifier, callback);
  } else {
    var id = this._getId(selector);
    Meteor.call('_su_', this.name, id, modifier, callback);
  }
};

SmartCollection.prototype.remove = function(selector, callback) {
  if(this._isSimulation()) {
    this._remoteCollection.remove(selector, callback);
  } else {
    var id = this._getId(selector);
    Meteor.call('_sr_', this.name, id, callback);
  }
};

SmartCollection.prototype._getId = function(selector) {
  var id;
  if(typeof(selector) == 'string') {
    id = selector;
  } else if(typeof(selector) == 'object' && typeof(selector._id) == 'string') {
    id = selector._id;
  }

  if(!id) {
    throw new Meteor.Error('403', 'Not permitted. Untrusted code may only update documents by ID');<commit_msg>added imediate propergation, but not tested yet<commit_after>function SmartCollection(name) {
  var self = this;
  this.name = name;
  this._remoteCollection = new Meteor.Collection(name);
  this._localCollection = new Meteor.Collection(null);

  this._pipeHandler = this._pipe(this._remoteCollection, this._localCollection);

  //wrap methods from the _remoteCollection
  ['find', 'findOne', 'allow', 'deny'].forEach(function(field) {
    self[field] = function() {
      return self._localCollection[field].apply(self._localCollection, arguments);
    };
  });
}

SmartCollection.prototype.insert = function(doc, callback) {
  var self = this;
  //_si_ == smart insert :P
  if(!doc._id) {
    doc._id = Random.id();
  }

  if(this._isSimulation()) {
    this._remoteCollection.insert(doc, callback);
  } else {
    this._localCollection.insert(doc);
    Meteor.call('_si_', this.name, doc, afterInserted);
  }

  function afterInserted(err) {
    if(err) {
      //check the document in the remoteCollection
      var remoteDoc = self._remoteCollection.findOne(doc._id);
      if(!remoteDoc) {
        //only remove from localCollection if no such doc exits in the remoteCollection
        self._localCollection.remove(doc._id);
      }
    }

    if(callback) callback(err);
  }
  return doc._id;
};

SmartCollection.prototype.update = function(selector, modifier, callback) {
  var self = this;
  if(this._isSimulation()) {
    this._remoteCollection.update(selector, modifier, callback);
  } else {
    var id = this._getId(selector);
    this._localCollection.update(selector, modifier);
    Meteor.call('_su_', this.name, id, modifier, afterUpdated);
  }

  function afterUpdated(err) {
    if(err) {
      var remoteDoc = self._remoteCollection.findOne(selector);
      if(remoteDoc) {
        self._localCollection.update(selector, {$set: remoteDoc});
      }
    }

    if(callback) callback(err);
  }
};

SmartCollection.prototype.remove = function(selector, callback) {
  var self = this;
  if(this._isSimulation()) {
    this._remoteCollection.remove(selector, callback);
  } else {
    var id = this._getId(selector);
    this._localCollection.remove(selector);
    Meteor.call('_sr_', this.name, id, afterRemoved);
  }

  function afterRemoved(err) {
    if(err) {
      var remoteDoc = self._remoteCollection.findOne(selector);
      if(remoteDoc) {
        self._localCollection.insert(remoteDoc);
      }
    }

    if(callback) callback(err);
  }
};

SmartCollection.prototype._getId = function(selector) {
  var id;
  if(typeof(selector) == 'string') {
    id = selector;
  } else if(typeof(selector) == 'object' && typeof(selector._id) == 'string') {
    id = selector._id;
  }

  if(!id) {
    throw new Meteor.Error('403', 'Not permitted. Untrusted code may only update documents by ID');
{'fraction_non_alphanumeric': 0.14197394568337382, 'fraction_numerical': 0.0013247957606535659, 'mean_word_length': 3.778481012658228, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1746226', 'n_tokens_mistral': 1437, 'n_tokens_neox': 1396, 'n_words': 288}