Meteor-Community-Packages / ground-db

GroundDB is a thin layer providing Meteor offline database and methods
https://atmospherejs.com/ground/db
MIT License
569 stars 76 forks source link

Remove is inconsistent #208

Closed CaptainN closed 4 years ago

CaptainN commented 6 years ago

I'm trying to use Ground:DB for offline storage. I'm manually copying and removing things from a remote service (no observeSource). Everything is working fairly well except I can't get documents to remove from the grounded collection reliably.

I thought it might be that MiniMongo wouldn't let me remove more than one document, so I reworked my remove code to iterate a cursor and remove each doc by _id. Documents seem to get removed in the same code block - meaning, it'll show 30 docs, then I iterate and remove, then another .find().fetch() shows 0. But other code subscribed to the resource will still show the documents - and they come back after refresh. The documents also don't consistently remove from indexedDB according to Chrome dev tools.

Eventually the documents do seem to get removed correctly, but I can't figure out why - what's the difference with those times?

I'm certain I'm not refilling the offline collection with docs from the server's collections, because the problem persists (for a while) even if I reset the remote collection.

For a workaround - is there a way to grab the backing localforage instance so I can remove documents directly in there?

CaptainN commented 6 years ago

Using OfflineDocs.storage.removeItem(_id) didn't work any better. Maybe a bug in localforage?

CaptainN commented 6 years ago

Okay, I think I got it working- I think I may have simply been trying to iterate over the records, before localforage (and ground db) had completely booted. I added an await OfflineDocs.storage.ready() statement before iteration, and it seems to have fixed the problem.

I hadn't realized there was a startup period to consider before interacting with the offline cache. Even stranger, it appears as though the backing store will be partially available before .ready(), which is why I think it was only removing some documents, and only eventually removing everything (in cases where my remote load was delayed for whatever reason). This also explains why I wasn't seeing the problem as much when connected to a (slower) remote mongo db (I'm iterating the cache, after I get replacements from remote).

Perhaps this should be documented somewhere?

https://localforage.github.io/localForage/#driver-api-ready

Here's my eventual code:

  let docs
  try {
    docs = await Methods.getDocList()
  } catch (error) {
    console.error(error)
  }

  await OfflineDocs.storage.ready()

  // delete all offline grids that aren't local-revisions
  const remDocs = OfflineDocs.find({status: {$ne: 'revision-local'}})
  remDocs.forEach((doc) => OfflineDocs.remove(doc._id))

  // now add/update anything we got from the server
  docs.forEach(doc => {
    // NOTE: upsert can't insert full documents - so we remove and insert instead
    // TODO: Don't remove/update docs with local edits
    OfflineDocs.remove({
      _id: doc._id
    })
    OfflineDocs.insert(slideShow)
    // console.info(`Cache Loader: Doc "${doc.name}" cached`)
  })