Ground DB Expert Needed

I made this post a few weeks ago regarding Ground DB. Unfortunately, there wasn’t much response. But, I’d like to check here once more before going elsewhere.

At this point we’re willing to pay a consultant fee for some assistance.

Original Post:
I’m working on a web app that users will, primarily be accessing from their phones. In some cases, it’s likely that I will have users that need to work with the app from remote locations with little to no network availability. So, I need it to be available offline.

AppCache works like a charm. I can browse to my app, completely offline, and get all of the basic components and UI.

Now I need persistent local data, so if the user ends up in a remote area they can load the app with the data that was last available to them online. GroundDB seems to be the answer, but I’ve had no luck so far.

I’m grounding my collections in template “onRendered” callbacks like this

Template.myTemplate.onRendered(function() {
Ground.Collection(example);
});
Which seems to be working despite getting this error for each doc in the collection. (Meteor does not currently support objects other than ObjectID as ids)

However, if I re-open the app in a new window while offline I get no data.

Right now, I’m making my subscriptions template level. Does that need to change? I’ve seen some older posts elsewhere about GroundDB, and it seems more common to have subscriptions hooked into your routes.

Does data need to be published differently with GroundDB?

After fighting with this for most of the day, I’m feeling more lost than when I started. I’m hoping somebody has a success story they can share that can either point me in the right direction with GroundDB, or just tell me I’m going about this all wrong.

Any input will be greatly appreciated.

We use GroundDB in our application.

Creating collections in OnRendered is probably not the best way to go about doing this. You should just create your collections in Meteor.startup, so they don’t get created every time the template re-renders.

It’s possible that you’re causing some bugs in GroundDB by having it create the collection multiple times over and over again whenever your template is rendered.

1 Like

Yes. Thanks for replying.
I should’ve altered my original post a little bit. You’re absolutely right about not creating or grounding the collections in onRendered. I’ve realized the flaw in my thinking, and have since gone away from that.

At this point, I’ve just taken the ground code out until I understand what I’m doing.

Currently, I’m just creating my collections independent of anything like Meteor.startup.

My subscriptions are set inside of a Tracker.autorun if that means anything.

Are you saying that I should be both creating and grounding my collections inside of Meteor.startup? I think I remember reading that this was the suggested practice somewhere else, but I never had any success.

Does grounding collections have any effect on how the data should be published or subscribed to?

You should simply create your collections as Ground collections, and use them normally.

Collections usually should only be initialized one time- this is regardless of them being GroundDB collections or not.

GroundDB has some time sensitive code that, when a Collection is initialized, and then a subscription is made, will listen to when the subscription has achieved a ‘ready’ state, and save the state of that subscription to permanent storage.

It will then listen to changes, updates, etc etc, and update the permanent storage as needed.

I think by reinitializing the collection over and over again in onRendered, you could very easily break the attachment between the subscription, and this collection, and cause GroundDB to do some very strange things.

Using a Grounded database shouldn’t have any effect on pub/sub logic. It only effects when you leave your application and return to it. Your subscription will not achieve a ‘ready’ state, but it will be preloaded with data, and ground’s ‘ready’ state will be set after restoring all of your collections.

This allows you to present that data in an offline mode. You should be aware of the fact however that when meteor connects, it will repull ALL of the subscribed data, and resave it in Ground.

Another side effect is, GroundDB does synchronize (Since it is using localStorage) changes between tabs.

I.E: If you have a subscription in one tab, and a different one in the other, GroundDB will make both of those subscriptions have the same values when you make changes to one or the other.

Thanks for the detailed explanation. You’re helping me understand this a little better.

Now, I know things are, partially working because, when testing the app on my phone and monitoring things from Safari’s developer window, I can see all of my data in Local Storage. And, it remains there even when I go completely offline and reload the app in a new browser window. However, I just get a blank screen offline.

I know you said GroundDB shouldn’t have any effect on pub/sub logic, but this behavior is making me feel like I’ve made a mistake with my subs.

This is now how I am initializing my grounded collections.

Meteor.startup(function() {
  Orders = new Ground.Collection("orders collection on the server");
  Details = new Ground.Collection("details collectoin on the server");
  Photos = new Ground.Collection("photo collection on the server");
  Profiles = new Ground.Collection("profiles collection on the server");

  Ground.Collection(Meteor.users);
});

This is how the data is being published.

Meteor.publish("orders", function () {
    if (this.userId)
        return Orders.find();
    else
	return this.ready();
});

Meteor.publish("details", function () {
    if (this.userId)
	return Details.find();
    else
	return this.ready();
});

Meteor.publish("photos", function () {
     if (this.userId)
    	return Photos.find();
     else
    	return this.ready();
});

Meteor.publish("profiles", function () {
   if (this.userId)
      return Profiles.find();
   else
      return this.ready();
});

And, this is how the subs look.

Tracker.autorun(function () {
    var ordersSub = Meteor.subscribe('orders');
    var detailsSub = Meteor.subscribe('details');
    var photosSub = Meteor.subscribe('photos');
    var profilesSub = Meteor.subscribe('profiles');
});

Based on what you’ve told me and what I’ve read elsewhere, this seems like it should work, but I have to be missing something here. Any possible suggestions?

So the Tracker.autorun isn’t needed since your subscriptions have nothing reactive to change on.

For GroundDB ‘ready’ will not occur for collections until their subscriptions have returned. So in offline mode, you should rely on Ground.ready for determining when the collection is filled with Grounded data.

Can you debug via a terminal and try ‘Orders.find().count()’ to check if those collections are being filled with data?

Yes. Well, I just use Safari to debug, but when completely offline, I try find().count() on any of my collections, and they have no data.

Okay, so, you do when you’re online see data? Can you add a callback to the subscriptions, and check that they are achieving a ready state?

You said earlier you see the localstorage is being filled with data, correct?

  • Jason

Yes

Yes. I just tried this:

Tracker.autorun(function () {
    var ordersSub = Meteor.subscribe('orders', {
      onReady: function() {console.log("Orders ready");}
    });
    var detailsSub = Meteor.subscribe('details', {
      onReady: function() {console.log("Details ready");}
    });
    var photosSub = Meteor.subscribe('photos', {
      onReady: function() {console.log("Photos ready");}
    });
    var profilesSub = Meteor.subscribe('profiles', {
      onReady: function() {console.log("Profiles ready");}
    });
});

Online, I see the subs achieve “ready”, but offline, they do not.

Yes. Even when offline, my data still exists in local storage.

If you want to provide a sample application, I can definitely help.

It doesn’t seem like GroundDB is working correctly in your application for some reason.

Thank for helping troynt out with our ground DB issues. It seems like your latest suggestion about downgrading ground db has grounded some data but only the data that was initially created on the mobile device. When we populate the data from an import on the mongo server we get documents with an (Object ID) type -vs- (String ID) type when created on the phone. It now looks like we can only ground (string ID) type documents. Any ideas?

Ah, actually, Troynt explained it much better in his private message.

I understand your issue is that the ObjectID is being used instead of a string ID for externally imported documents.

So, can you possibly change the _id field to a string ID, and store the objectID field in another field for matching it up with your external source?

Otherwise, I think you may have to modify GroundDB, because it’s clearly experiencing a bug matching these ObjectIDs to items in localstorage.

Yes you have it. We are importing bulk data for testing and during that process the OBJECT ID field is created. We are not currently using that for anything. it is a by-product of the import. 95% of the data will be pushed to our devices with minor update and pictures added on those devices. seems like we need to import as string ID which would possibly solve our ground DB bug. I was under the impression that the string ID or OBJECT ID was generated to handle the reactive data management in Mongo. Thoughts? and thanks for your import - very much appreciated!

Hello thedracle, I have no idea how to use that method (Ground.ready()), it doesn’t appear to be documented. Please could you explain how to use this method and what’s it’s purpose?