Skip to content
raix edited this page Sep 24, 2014 · 1 revision

Documentation of ground:db

ground:db adds some features to the regular Mongo.Collection object in Meteor.

EventEmitter

Physically we add an event emitter to the Mongo.Collection.prototype - This allows ground:db to emit events directly on the Mongo.Collection object. We are using the raix:eventemitter that supports the node.js EventEmitter api. The global GroundDB is also an EventEmitter, and the localstorage adapter Store.localStorage is too an EventEmitter.

Overwriting the default Mongo.Collection.prototype.insert

GrounDB Modify the way documents are inserted into a Mongo.Collection

Meteor doesnt always make sure documents have an _id attached. We need this because its our only way to allow offline resume of Meteor.mehtods calls. Normally Meteor handles poor connections keeping a record of "out standing methods" - but they rely on a invocation callback, when the user closes the page this data is lost.

But overwriting the default insert method forcing an _id on grounded collections makes ground:db capable of resuming those method calls. The returning methods are emitted via the global GroundDB event emitter to catch these method calls use:

GroundDB.addListener('method', function(method, error, result) {
  // Method has returned!
});

Overwriting the default self.connection._stores[ name ].update

This part is indeed the most hacky part of overwriting default Meteor. But again - A default Mongo.Collection cannot grasp if the local collection already contains documents. This makes sense in a normal situation, but ground:db populates the local collection with the last subscription data before the new subscription is settled. Its a hack, but the hack also allows future client-side conflict handlers.

Client-side conflict handlers

Why client-side conflict handling? So its the only place we can really ask the user for help if we have trouble migrating data. One bigger issue is that Meteor lets the last document hitting the server win. So in an offline situation this is not correct - it should be the newest data that wins or perhaps another custom conflict resolution? The base for this stuff to make sense is prepared in ground:db, pr. default the ground:servertime package provides an api for the client to obtain the server timestamp even if offline.

The QA test for the conflict resolver is written - though its currently failing due to the missing implementation... It'll come in time.

Local storage adapters

As briefly mentioned ground:store makes sure to return the best storage available. At the moment theres only written one local storage adapter ground:localstorage - its has an async api, preparing ground:db to be able to use eg. the Cordova filesystem and others for larger storage support. ground:localstorage also provides namespaced functions and events making it much easier to work with larger data sets.

Sync between tabs

Yeah, its a basic feature that allows offline collections to sync between tabs. It also allows eg. one offline tab to use another tabs connection etc.

How to use this thing?

Its pretty flexible, first create an instance eg.:

  // Use an existing Mongo.Collection
  var foo = new Mongo.Collection('foo');
  GroundDB(foo);

  // Create a new grouned Mongo.Collection
  var bar = new Ground('bar');

Adding versions on databases

What's up with the version stuff I saw somewhere? So pr. default a local store keeps track of versions, if version changes it can migrate data from one version to another - the default behaviour is simply to clear the data. And the default version is 1.0 so if we created the instance as.:

  // Bump and clean the storage:
  var foo = new GroundDB('foo', { version: 1.1 });

  // Or add a custom migration function
  var foo = new GroundDB('foo', {
    version: 1.1,
    migration: function(oldRecord, newRecord) {
      /* this is storage, do something clever */
    }
  });