apache / apache/pouchdb

Document Deletion Not Replicated with Low revs_limit (CouchDB → PouchDB)

Open
#9,085 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
17.6k
Forks
1.5k
PR merge metrics
No merged PRs in 30d

Description

# 🔄 Document Deletion Not Replicated with Low `revs_limit` (CouchDB → PouchDB)

Hi,

I'm encountering a document deletion issue when replicating data from CouchDB to PouchDB with a low `revs_limit`.

## 🧠 Context

I'm using a one-way replication mechanism from CouchDB → PouchDB in a React Native application. Documents are updated daily in CouchDB and replicated to PouchDB. No changes are made in PouchDB — it's read-only.

Because documents were accumulating hundreds of revisions (sometimes 400+), we decided to limit the revision history by setting `revs_limit = 1` on the CouchDB database, since we do not need any revision history.

This approach generally works well — documents update fine even with multiple revision gaps.

## ❌ Problem: Deletions Are Not Propagated

However, we're running into a problem with deleted documents not being removed from PouchDB.

### 🧪 Reproduction Scenario (with `revs_limit = 3`)

1. A document is created in CouchDB.
2. It is replicated to PouchDB.
3. The document is modified 6 times in CouchDB.
4. The document is then deleted in CouchDB.
5. The replication is triggered.

➡️ At this point, the document is NOT deleted in PouchDB.

If I increase `revs_limit` to 10 with same process, the deletion propagates correctly.

## 🧩 Investigation

The deletion status is determined via this code (extracted from PouchDB):

```js
// check if a specific revision of a doc has been deleted
// - metadata: the metadata object from the doc store
// - rev: (optional) the revision to check. defaults to winning revision
function isDeleted(metadata, rev) {
if (!rev) {
rev = winningRev(metadata);
}
var id = rev.substring(rev.indexOf('-') + 1);
var toVisit = metadata.rev_tree.map(getTrees);

var tree;
while ((tree = toVisit.pop())) {
if (tree[0] === id) {
return !!tree[1].deleted;
}
toVisit = toVisit.concat(tree[2]);
}
}
```

Here’s an example of the replicated document metadata:

```json
{
"id": "header:test7",
"deleted": true,
"revisions": {
"start": 7,
"ids": [
"6f8c91dbbaeaddfc94972b3b912a8b43",
"1e0a89380ff99cc556d5f8518afb39a7",
"520f3eb9ca9c2f925f63b363c80774ae"
]
},
"rev_tree": [
{
"pos": 1,
"ids": ["637b045152350553a2ad642d05975297", { "status": "available" }, []]
},
{
"pos": 5,
"ids": [
"520f3eb9ca9c2f925f63b363c80774ae",
{ "status": "missing" },
[
[
"1e0a89380ff99cc556d5f8518afb39a7",
{ "status": "missing" },
[
[
"6f8c91dbbaeaddfc94972b3b912a8b43",
{ "status": "available", "deleted": true },
[]
]
]
]
]
]
}
],
"seq": 8840
}
```

In this case:

- The rev at `pos: 1` corresponds to the first revision (from the initial replication).
- The rev at `pos: 5` corresponds to the deleted revision.
- However, the ID passed to the function is the one from `pos: 1` (`637b045152350553a2ad642d05975297`), which doesn't match the deleted branch in the `rev_tree`.

Thus, the document never gets deleted in PouchDB.

## ❓ Question

Is this expected behavior when using a low `revs_limit`?
Is there a way to ensure that document deletions replicate correctly even when the deleted revision is from a "longer" branch that replaces a truncated one?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.