Skip to content

Commit f5463ad

Browse files
author
hideki
committed
Fixed #1593 - Missing changes on changes feed (Mac <- Android) pull replication
Same issue with https://github.com/couchbase/couchbase-lite-java-core/issues/1495 Referenced previous PR: #1521 , but this PR caused another another issue with `/_changes` REST API. Notes: - In case of `/_changes?feed=longpoll` REST API, there is case document is inserted or updated between calling `changesSince()` method and starting to observe Database change event. It could causing unhandled documents. This usually is caused by calling POST/PUT /{db}/{docID} and calling POST/GET /{db}/_changes?feed=longpool concurrently. - To avoid above scenario, calling changesSince() method in DatabaseListener changed() callback method to make sure if any document changes occurs between them. - Fixed the case startTimeout() is not called at line 1737. - Make sure to set correct `since` value by deleting the method `sendLongpollChanges(rev)` that uses 0 as since value.
1 parent 665ea66 commit f5463ad

1 file changed

Lines changed: 28 additions & 9 deletions

File tree

src/main/java/com/couchbase/lite/router/Router.java

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ private enum TDContentOptions {
114114
private URL source = null;
115115

116116
// _changes request:
117+
private boolean filled = false;
118+
private long changesSince = 0;
119+
private ChangesOptions changesOptions = null;
117120
private ReplicationFilter changesFilter;
118121
Map<String, Object> changesFilterParams = null;
119122
private boolean longpoll = false;
@@ -1644,10 +1647,6 @@ private void sendContinuousChangeLastSequenceAndFinish(long lastSeq) {
16441647
}
16451648
}
16461649

1647-
private void sendLongpollChanges(List<RevisionInternal> revs) {
1648-
sendLongpollChanges(revs, 0);
1649-
}
1650-
16511650
private void sendLongpollChanges(List<RevisionInternal> revs, long since) {
16521651
// Ensure that the content type is application/json:
16531652
connection.getResHeader().add("Content-Type", CONTENT_TYPE_JSON);
@@ -1700,6 +1699,19 @@ public void changed(Database.ChangeEvent event) {
17001699
// Stop timeout timer:
17011700
stopTimeout();
17021701

1702+
// In race condition, new doc or update doc is fired before starting to observe the
1703+
// DatabaseChangeEvent, it allows to skip few document changes with /_changes REST API.
1704+
// Make sure all document changes are tread by /_changes REST API.
1705+
if (!filled) {
1706+
filled = true;
1707+
RevisionList changes = db.changesSince(changesSince, changesOptions,
1708+
changesFilter, changesFilterParams);
1709+
if (changes.size() > 0) {
1710+
sendLongpollChanges(changes, changesSince);
1711+
return;
1712+
}
1713+
}
1714+
17031715
List<RevisionInternal> revs = new ArrayList<RevisionInternal>();
17041716
List<DocumentChange> changes = event.getChanges();
17051717
for (DocumentChange change : changes) {
@@ -1734,13 +1746,11 @@ else if (!winningRevID.equals(rev.getRevID())) {
17341746
timeoutLastSeqence = rev.getSequence();
17351747
}
17361748

1737-
if (longpoll) {
1738-
if (revs.size() > 0)
1739-
sendLongpollChanges(revs);
1740-
} else {
1749+
if (longpoll && revs.size() > 0)
1750+
sendLongpollChanges(revs, changesSince);
1751+
else
17411752
// Restart timeout timer for continuous feed request:
17421753
startTimeout();
1743-
}
17441754
}
17451755
}
17461756

@@ -1820,6 +1830,15 @@ private Status doChanges(Database db) {
18201830
timeoutLastSeqence = rev.getSequence();
18211831
}
18221832
}
1833+
1834+
// set following parameters to call Database.changesSince(...) in changed(...) callback
1835+
// to fill the gap between changesSince() and changed() callbacks.
1836+
// https://github.com/couchbase/couchbase-lite-java-core/issues/1495
1837+
filled = false;
1838+
changesSince = since;
1839+
changesOptions = options;
1840+
1841+
// To observe database change event
18231842
db.addChangeListener(this);
18241843

18251844
//timeout

0 commit comments

Comments
 (0)