c4db_purgeDoc & sync

Hi,

I’m exploring the capabilities of lite core api.

When I create a document, it is placed on the database by the replicator via sync-gateway.

However, when I delete a document with c4db_purgeDoc it vanishes from my local database but stays in remote database.

Is this the expected behaviour?

For me it is not right and I need to understand what is going on in order to move forward.

Thanks in advance!

Regards,

Nuno

This is the right behavior. When purging a local document, only the local copy of the document will be removed. You can delete a document instead so that the deletion could be synced to Sync Gateway. However delete a document will not completely delete a local document, it will create a new tombstone revision that can be synced.

@pasin thanks for your reply. What’s the api call to delete a document like you have said?

I need to have the contents of a bucket replicated through several devices. When I delete a document from my local device I want it to disappear from the other devices as well. Does this make sense?

@sinosoidal, you can use this API, .deleteDocument() to delete doc for couchblite 2.0 and up.
Also make sure you replication is continuous or start a new replication in order to replicate deletion on all devices.

The way to save a deletion in LiteCore is to set the kRevDeleted flag on the revFlags property of the put request.

C4DocPutRequest rq = {};
// ...
rq.revFlags = kRevDeleted; // + whatever else you need

Thanks for your replies and help.

So a deleted document is never actually deleted. It will only be marked as deleted through the flag kRevDeleted and will never leave the local or remote database. Is this correct?

So, when I list all the documents, should I filter the output to not include documents that have the kRevDeleted flag? What’s the recommended approach?

What’s the best document of Coouchbase documentation to refer to database design and basic operations overview?

Thanks!

Correct

Incorrect. The entire reason things are done this way is so that a deletion can be synced to a remote endpoint (or multiple).

This is done by default unless you specifically request deleted documents. EDIT This is true for Couchbase Lite but I am not 100% sure if Couchbase Lite abstracts this behavior or not so don’t take my word on that.

LiteCore is not an officially supported project on its own, and does not have any documentation other than what is on the wiki of the GitHub repo. Know that you face dragons if you take on this project directly, but that being said it is the core component of Couchbase Lite and is not going to disappear.

@borrrden thank you very much for your clarifications.

In the end I still don’t get what’s the purpose of the call c4db_purgeDoc and specially it’s descriptions. Does

Removes all trace of a document and its revisions from the database.

apply to local database only?

@borrrden I have tried to delete a document the way you suggested and in between a transaction I have made this

C4DocPutRequest rq = {};
rq.docID = (QSlString) document->id();
rq.save = true;
rq.existingRevision = false;
rq.revFlags = kRevDeleted;
c4::ref<C4Document> docNew = c4doc_put(_c4Database, &rq, nullptr, &c4err);

if (!docNew)
{
    logC4Error(QString("Unable to delete document, docId = %1").arg(document->id()), c4err);
    exit(-1);
} 

But it failed to delete the document with the following error:

Unable to delete document, docId = 0000016: Can’t create a new already-deleted document

I can’t understand the error message.

What am I missing?

Thanks!

Nuno

Purging is for local only removal of a document. It’s useful if you are wanting to save space on your device but don’t want the documents to be deleted elsewhere. It’s a little fragile in that if you get another update to the document later it will come back, but with proper care it can help save some space on the local device.

The thing you are missing about deletions is basically the entire way that things get saved in the backend. You don’t just write a document and then later write it again with the same ID to change it, because that’s not safe at all for distributed systems. You need to maintain a revision history tree by making your edits on top of the previous one (if two different clients make an edit to the same document then you’ve got a “conflict” just like in Git). I’d suggest looking through the tests in c4DocumentTest.cc to get a better understanding of how it works but at a high level, you need to establish a history back to an existing revision in order to save a deletion (you cannot simply create a new document that is already deleted). That means you need to get the revision ID of the previous existing revision and add it to the request’s history before you attempt to save.

@borrrden yes, I understand that a revision tree must be saved.

I ended up with this approach to delete a document. It seems to be working. Please let me know your thoughts.

C4RevisionFlags flags = kRevKeepBody;

if (deleted)
    flags |= kRevDeleted;

c4::ref<C4Document> c4Doc(c4doc_update(c4CurrDoc, body, flags, &c4err));

if (!c4Doc)
{
    logC4Error(QString("Unable to update, docId = %0").arg(document->id()), c4err);

    return false;
}

Thanks for your help!

Regards,

Nuno

Ah yes I forgot about c4doc_update. That is the preferred method actually. Beware that kRevKeepBody is possibly not entirely reliable so don’t count on it.

@borrrden thanks for the update. If I want to delete I don’t care the body anyway, right? Should I leave it or take it out?

Queries ignore deleted docs, unless you explicitly refer to the ._deleted property in the where clause.

You can make a deleted doc disappear eventually by setting an expiration date on it. Or you can purge all deleted docs (we call those “tombstones”) by querying for them and calling Purge on each one.

Bodies of deleted docs are usually empty. There are some cases where you’d want to put data in a deleted doc, to get it assigned to the right channel in Sync Gateway, but it’s not common.