From 326fce8bf31eddfa83a3cc57a69fa4b3eb97dc21 Mon Sep 17 00:00:00 2001 From: ibsoln <52778946+ibsoln@users.noreply.github.com> Date: Tue, 23 Feb 2021 10:26:00 +0000 Subject: [PATCH] DOC-7519 -- Pending Doc Ids not documented https://issues.couchbase.com/browse/DOC-7519 merged prior commits ... DOC-7519 -- JAVA Snippets https://issues.couchbase.com/browse/DOC-7519 Pending Doc Ids not documented DOC-7519 -- iOS Snippets https://issues.couchbase.com/browse/DOC-7519 Pending Doc Ids not documented DOC-7519 -- C# Snippets https://issues.couchbase.com/browse/DOC-7519 Pending Doc Ids not documented DOC-7519 -- Pending Doc Ids not documented https://issues.couchbase.com/browse/DOC-7519 DOC-7519 -- iOS Snippets (objc) Simplify iteration look at ln 875 https://issues.couchbase.com/browse/DOC-7519 Revert "DOC-7519 -- iOS Snippets (objc)" This reverts commit d9ee906c646622db95204e282bbd4aa5b265e1aa. DOC-7519 -- iOS Snippets (objc) https://issues.couchbase.com/browse/DOC-7519 Simplify iteration look at ln 875 DOC-7519 - Apply changes to Java snippets https://issues.couchbase.com/browse/DOC-7519 --- .../commons/common-sgw-replication.adoc | 31 ++++++- .../com/couchbase/code_snippets/Examples.java | 85 ++++++++++++++++++- .../pages/_partials/_attributes-module.adoc | 2 +- .../csharp/examples/code_snippets/Program.cs | 50 ++++++++++- .../pages/_partials/_attributes-module.adoc | 4 +- .../java/examples/code_snippets/Examples.java | 83 ++++++++++++++++++ .../pages/_partials/_attributes-module.adoc | 4 +- .../examples/code_snippets/SampleCodeTest.m | 56 ++++++++++++ .../pages/_partials/_attributes-module.adoc | 14 ++- .../code_snippets/SampleCodeTest.swift | 39 +++++++++ .../pages/_partials/_attributes-module.adoc | 4 +- 11 files changed, 353 insertions(+), 19 deletions(-) diff --git a/modules/ROOT/pages/_partials/commons/common-sgw-replication.adoc b/modules/ROOT/pages/_partials/commons/common-sgw-replication.adoc index c3f92e67c..8c68c3df3 100644 --- a/modules/ROOT/pages/_partials/commons/common-sgw-replication.adoc +++ b/modules/ROOT/pages/_partials/commons/common-sgw-replication.adoc @@ -236,7 +236,7 @@ include::{snippet}[tag=replication-reset-checkpoint,indent=0] == Monitoring In this section:: -<> | <> | <> +<> | <> | <> | <> You can monitor a replication’s status by using a combination of <> and the `replication.status.activity` property -- see; {url-api-enum-replicator-activity}. This enables you to know, for example, when the replication is actively transferring data and when it has stopped. @@ -319,6 +319,35 @@ include::{snippet}[tag=remove-document-replication-listener,indent=0] When access to a document is removed on Sync Gateway (see: Sync Gateway's xref:sync-gateway::sync-function-api.adoc[Sync Function]), the document replication listener sends a notification with the `AccessRemoved` flag set to `true` and subsequently purges the document from the database. -- +[#lbl-repl-pend] +=== Documents Pending Push + +TIP: {url-api-method-replicator-isDocumentPending} is quicker and more efficient. +Use it in preference to returning a list of pending document IDs, where possible. + +You can check whether documents are waiting to be pushed in any forthcoming sync by using either of the following API methods: + +* Use the {url-api-method-replicator-getPendingDocumentIds} method, which returns a list of document IDs that have local changes, but which have not yet been pushed to the server. ++ +This can be very useful in tracking the progress of a push sync, enabling the app to provide a visual indicator to the end user on its status, or decide when it is safe to exit. + +* Use the {url-api-method-replicator-isDocumentPending} method to quickly check whether an individual document is pending a push. + +[#ex-pending] +.Use Pending Document ID API +==== + +[source, {source-language}] +---- +include::{snippet}[tags=replication-pendingdocuments, indent=0] + +---- +<.> {url-api-method-replicator-getPendingDocumentIds} returns a list of the document IDs for all documents waiting to be pushed. +This is a snapshot and may have changed by the time the response is received and processed. + +<.> {url-api-method-replicator-isDocumentPending} returns `true` if the document is waiting to be pushed, and `false` otherwise. + +==== [#lbl-repl-stop] == Stop Sync diff --git a/modules/android/examples/java-android/app/src/main/java/com/couchbase/code_snippets/Examples.java b/modules/android/examples/java-android/app/src/main/java/com/couchbase/code_snippets/Examples.java index 1d3e2aeae..0a68a5fff 100644 --- a/modules/android/examples/java-android/app/src/main/java/com/couchbase/code_snippets/Examples.java +++ b/modules/android/examples/java-android/app/src/main/java/com/couchbase/code_snippets/Examples.java @@ -894,10 +894,91 @@ public void testReplicationStatus() throws URISyntaxException { if (change.getStatus().getActivityLevel() == Replicator.ActivityLevel.STOPPED) { Log.i(TAG, "Replication stopped"); } - }); - // end::replication-status[] + }); + // end::replication-status[] + } + + // BEGIN PendingDocuments BM -- 19/Feb/21 -- + import android.support.annotation.NonNull; + import android.util.Log; + + import java.net.URI; + import java.net.URISyntaxException; + import java.util.Iterator; + import java.util.Set; + + import com.couchbase.lite.CouchbaseLiteException; + import com.couchbase.lite.Database; + import com.couchbase.lite.Endpoint; + import com.couchbase.lite.Replicator; + import com.couchbase.lite.ReplicatorConfiguration; + import com.couchbase.lite.URLEndpoint; + + class PendingDocsExample { + private static final String TAG = "SCRATCH"; + + private Database database; + private Replicator replicator; + + // BEGIN PendingDocuments IB -- 11/Feb/21 -- + public void testReplicationPendingDocs() throws URISyntaxException, CouchbaseLiteException { + // tag::replication-pendingdocuments[] + // ... include other code as required + // + final Endpoint endpoint = + new URLEndpoint(new URI("ws://localhost:4984/db")); + + final ReplicatorConfiguration config = + new ReplicatorConfiguration(database, endpoint) + .setReplicatorType(ReplicatorConfiguration.ReplicatorType.PUSH); + // tag::replication-push-pendingdocumentids[] + + replicator = new Replicator(config); + final Set pendingDocs = + replicator.getPendingDocumentIds(); // <.> + + // end::replication-push-pendingdocumentids[] + + replicator.addChangeListener(change -> { + onStatusChanged(pendingDocs, change.getStatus()); }); + + replicator.start(); + + // ... include other code as required + // end::replication-pendingdocuments[] + } + // + // tag::replication-pendingdocuments[] + // + private void onStatusChanged( + @NonNull final Set pendingDocs, + @NonNull final Replicator.Status status) { + // ... sample onStatusChanged function + // + Log.i(TAG, + "Replicator activity level is " + status.getActivityLevel().toString()); + + // iterate and report-on previously + // retrieved pending docids 'list' + for (Iterator itr = pendingDocs.iterator(); itr.hasNext(); ) { + final String docId = itr.next(); + try { + // tag::replication-push-isdocumentpending[] + if (!replicator.isDocumentPending(docId)) { continue; } // <.> + // end::replication-push-isdocumentpending[] + + itr.remove(); + Log.i(TAG, "Doc ID " + docId + " has been pushed"); + } + catch (CouchbaseLiteException e) { + Log.w(TAG, "isDocumentPending failed", e); } + } + } + // end::replication-pendingdocuments[] + // END PendingDocuments BM -- 19/Feb/21 -- } + public void testHandlingNetworkErrors() throws URISyntaxException { Endpoint endpoint = new URLEndpoint(new URI("ws://localhost:4984/db")); ReplicatorConfiguration config = new ReplicatorConfiguration(database, endpoint); diff --git a/modules/android/pages/_partials/_attributes-module.adoc b/modules/android/pages/_partials/_attributes-module.adoc index bc93da6f9..9311a6ddd 100644 --- a/modules/android/pages/_partials/_attributes-module.adoc +++ b/modules/android/pages/_partials/_attributes-module.adoc @@ -217,7 +217,7 @@ :url-api-method-replicator-getPendingDocumentIds: {url-api-properties-replicator-abs}getPendingDocumentIds--[Replicator.getPendingDocumentIds()] -:url-api-method-replicator-isDocumentPending: {url-api-properties-replicator-abs}isDocumentPending--[Replicator.isDocumentPending()] +:url-api-method-replicator-isDocumentPending: {url-api-properties-replicator-abs}isDocumentPending-java.lang.String-[Replicator.isDocumentPending()] :url-api-method-replicator-start: {url-api-properties-replicator-abs}start-boolean-[start()] diff --git a/modules/csharp/examples/code_snippets/Program.cs b/modules/csharp/examples/code_snippets/Program.cs index e0f2a63f2..c1f14fa26 100644 --- a/modules/csharp/examples/code_snippets/Program.cs +++ b/modules/csharp/examples/code_snippets/Program.cs @@ -1074,6 +1074,55 @@ private static void SetupReplicatorListener() // end::replication-status[] } + + + + // BEGIN PendingDocuments IB -- 11/Feb/21 -- + private static void ReplicatorPendingDocuments() + { + // tag::replication-pendingdocuments[] + var url = new Uri("ws://localhost:4984/mydatabase"); + var target = new URLEndpoint(url); + var database = new Database("myDB"); + var config = new ReplicatorConfiguration(database, target); + config.ReplicatorType = ReplicatorType.Push; + + // tag::replication-push-pendingdocumentids[] + var replicator = new Replicator(config); + + var mydocids = + new HashSet (replicator.GetPendingDocumentIDs()); // <.> + + // end::replication-push-pendingdocumentids[] + + if (mydocids.Count > 0) + { + Console.WriteLine($"There are {mydocids.Count} documents pending"); + replicator.AddChangeListener((sender, change) => + { + Console.WriteLine($"Replicator activity level is " + + change.Status.Activity.ToString()); + // iterate and report-on previously + // retrieved pending docids 'list' + foreach (var thisId in mydocids) + // tag::replication-push-isdocumentpending[] + if (!replicator.IsDocumentPending(thisId)) // <.> + { + Console.WriteLine($"Doc ID {thisId} now pushed"); + }; + // end::replication-push-isdocumentpending[] + }); + + replicator.Start(); + } + // end::replication-pendingdocuments[] + } + + +// END PendingDocuments IB -- 11/Feb/21 -- + + + private static void ReplicatorDocumentEvent() { var replicator = _Replicator; @@ -1572,4 +1621,3 @@ public Document Resolve(Conflict conflict) } } // end::merge-conflict-resolver[] -} diff --git a/modules/csharp/pages/_partials/_attributes-module.adoc b/modules/csharp/pages/_partials/_attributes-module.adoc index d13be0315..1739f156f 100644 --- a/modules/csharp/pages/_partials/_attributes-module.adoc +++ b/modules/csharp/pages/_partials/_attributes-module.adoc @@ -227,9 +227,9 @@ :url-api-method-replicator-rmv-change-listener: {url-api-properties-replicator}RemoveChangeListener_Couchbase_Lite_ListenerToken_[RemoveChangeListener(ListenerToken)] -:url-api-method-replicator-getPendingDocumentIds: {url-api-properties-replicator}GetPendingDocumentIDs[Replicator.GetPendingDocumentIds()] +:url-api-method-replicator-getPendingDocumentIds: {url-api-properties-replicator}GetPendingDocumentIDs[Replicator.GetPendingDocumentIDs()] -:url-api-method-replicator-isDocumentPending: {url-api-properties-replicator}IsDocumentPending--[Replicator.IsDocumentPending()] +:url-api-method-replicator-isDocumentPending: {url-api-properties-replicator}IsDocumentPending_System_String_[Replicator.IsDocumentPending()] :url-api-method-replicator-start: {url-api-properties-replicator}Start[Start()] diff --git a/modules/java/examples/code_snippets/Examples.java b/modules/java/examples/code_snippets/Examples.java index c753054ec..a03867695 100644 --- a/modules/java/examples/code_snippets/Examples.java +++ b/modules/java/examples/code_snippets/Examples.java @@ -1389,6 +1389,89 @@ public void testReplicationStatus() throws URISyntaxException { // end::replication-status[] } + // BEGIN PendingDocuments BM -- 19/Feb/21 -- + import android.support.annotation.NonNull; + import android.util.Log; + + import java.net.URI; + import java.net.URISyntaxException; + import java.util.Iterator; + import java.util.Set; + + import com.couchbase.lite.CouchbaseLiteException; + import com.couchbase.lite.Database; + import com.couchbase.lite.Endpoint; + import com.couchbase.lite.Replicator; + import com.couchbase.lite.ReplicatorConfiguration; + import com.couchbase.lite.URLEndpoint; + + class PendingDocsExample { + private static final String TAG = "SCRATCH"; + + private Database database; + private Replicator replicator; + + // BEGIN PendingDocuments IB -- 11/Feb/21 -- + public void testReplicationPendingDocs() throws URISyntaxException, CouchbaseLiteException { + // tag::replication-pendingdocuments[] + // ... include other code as required + // + final Endpoint endpoint = + new URLEndpoint(new URI("ws://localhost:4984/db")); + + final ReplicatorConfiguration config = + new ReplicatorConfiguration(database, endpoint) + .setReplicatorType(ReplicatorConfiguration.ReplicatorType.PUSH); + // tag::replication-push-pendingdocumentids[] + + replicator = new Replicator(config); + final Set pendingDocs = + replicator.getPendingDocumentIds(); // <.> + + // end::replication-push-pendingdocumentids[] + + replicator.addChangeListener(change -> { + onStatusChanged(pendingDocs, change.getStatus()); }); + + replicator.start(); + + // ... include other code as required + // end::replication-pendingdocuments[] + } + // + // tag::replication-pendingdocuments[] + // + private void onStatusChanged( + @NonNull final Set pendingDocs, + @NonNull final Replicator.Status status) { + // ... sample onStatusChanged function + // + Log.i(TAG, + "Replicator activity level is " + status.getActivityLevel().toString()); + + // iterate and report-on previously + // retrieved pending docids 'list' + for (Iterator itr = pendingDocs.iterator(); itr.hasNext(); ) { + final String docId = itr.next(); + try { + // tag::replication-push-isdocumentpending[] + if (!replicator.isDocumentPending(docId)) { continue; } // <.> + // end::replication-push-isdocumentpending[] + + itr.remove(); + Log.i(TAG, "Doc ID " + docId + " has been pushed"); + } + catch (CouchbaseLiteException e) { + Log.w(TAG, "isDocumentPending failed", e); } + } + } + // end::replication-pendingdocuments[] + // END PendingDocuments BM -- 19/Feb/21 -- + } + + + + public void testHandlingNetworkErrors() throws URISyntaxException { Endpoint endpoint = new URLEndpoint(new URI("ws://localhost:4984/db")); ReplicatorConfiguration config = new ReplicatorConfiguration(database, endpoint); diff --git a/modules/java/pages/_partials/_attributes-module.adoc b/modules/java/pages/_partials/_attributes-module.adoc index f4ba6d3e6..a7267a12f 100644 --- a/modules/java/pages/_partials/_attributes-module.adoc +++ b/modules/java/pages/_partials/_attributes-module.adoc @@ -213,9 +213,9 @@ :url-api-method-replicator-stop: {url-api-properties-replicator-abs}stop--[stop()] -:url-api-method-replicator-getPendingDocumentIds: {url-api-properties-replicator-abs}getPendingDocumentIds--[Replicator.getPendingDocuments()] +:url-api-method-replicator-getPendingDocumentIds: {url-api-properties-replicator-abs}getPendingDocumentIds--[Replicator.getPendingDocumentIds()] -:url-api-method-replicator-isDocumentPending: {url-api-properties-replicator-abs}isDocumentPending--[Replicator.isDocumentPending] +:url-api-method-replicator-isDocumentPending: {url-api-properties-replicator-abs}isDocumentPending-java.lang.String-[Replicator.isDocumentPending] :url-api-property-replicator-status: {url-api-properties-replicator-abs}getStatus--[replicator.getStatus] diff --git a/modules/objc/examples/code_snippets/SampleCodeTest.m b/modules/objc/examples/code_snippets/SampleCodeTest.m index 475d67afa..f2b134809 100644 --- a/modules/objc/examples/code_snippets/SampleCodeTest.m +++ b/modules/objc/examples/code_snippets/SampleCodeTest.m @@ -836,6 +836,62 @@ - (void) dontTestReplicatorStatus { // end::replication-status[] } + +// BEGIN PendingDocuments IB -- 11/Feb/21 -- +// public void testReplicationPendingDocs() throws URISyntaxException { + // tag::replication-pendingdocuments[] + + CBLDatabase *database = self.db; + NSURL *url = [NSURL URLWithString:@"ws://localhost:4984/db"]; + CBLURLEndpoint *target = + [[CBLURLEndpoint alloc] initWithURL: url]; + CBLReplicatorConfiguration *config = + [[CBLReplicatorConfiguration alloc] + initWithDatabase:database + target:target]; + + config.replicatorType = kCBLReplicatorTypePush; + + // tag::replication-push-pendingdocumentids[] + CBLReplicator *replicator = + [[CBLReplicator alloc] initWithConfig:config]; + + // Get list of pending doc IDs + NSError* err = nil; + NSSet *mydocids = + [NSSet setWithSet:[replicator pendingDocumentIDs:&err]]; // <.> + + // end::replication-push-pendingdocumentids[] + + if ([mydocids count] > 0) { + + NSLog(@"There are %lu documents pending", (unsigned long)[mydocids count]); + + [replicator addChangeListener:^(CBLReplicatorChange *change) { + + NSLog(@"Replicator activity level is %u", change.status.activity); + // iterate and report-on the pending doc IDs in 'mydocids' + for (thisid in mydocids) { + + // tag::replication-push-isdocumentpending[] + NSError* err = nil; + if (![replicator isDocumentPending: thisid error: &err]) { // <.> + NSLog(@"Doc ID %@ now pushed", thisid); + } + // end::replication-push-isdocumentpending[] + } + + }]; + [replicator start]; + + }; + + // end::replication-pendingdocuments[] + } +// END PendingDocuments IB -- 11/Feb/21 -- + + + - (void) dontTestReplicatorDocumentEvent { CBLDatabase *database = self.db; NSURL *url = [NSURL URLWithString:@"ws://localhost:4984/db"]; diff --git a/modules/objc/pages/_partials/_attributes-module.adoc b/modules/objc/pages/_partials/_attributes-module.adoc index 68bb13681..3ac3c1acf 100644 --- a/modules/objc/pages/_partials/_attributes-module.adoc +++ b/modules/objc/pages/_partials/_attributes-module.adoc @@ -39,14 +39,10 @@ :url-api-method-database-deletedoc-concctrl: {url-api-method-database}deleteDocument:concurrencyControl:error:[{api-pfx}Database -deleteDocument:concurrencyControl:error:] - - - - //Database.COMPACT -:url-api-method-database-compact: {url-api-method-database}compact:[CBLDatabase.compact()] +:url-api-method-database-compact: {url-api-method-database}compact:[{api-pfx}Database.compact()] :url-api-method-database-copy: {url-api-references-database}{url-api-references-objc-sep}CBLDatabase(cm)copyFromPath:toDatabase:withConfig:error:[copyFromPath()] -:url-api-method-database-performMaintenance: {url-api-method-database}performMaintenance:error:[CBLDatabase.performMaintenance()] +:url-api-method-database-performMaintenance: {url-api-method-database}performMaintenance:error:[{api-pfx}Database.performMaintenance()] :url-api-method-database-setloglevel: {url-api-references-database}{sep}c:objc(cs)CBLDatabase(cm)setLogLevel:domain:[{api-pfx}Database.setLogLevel()] @@ -174,9 +170,9 @@ :url-api-method-replicator-rmv-change-listener: {url-api-properties-replicator}(im)removeChangeListenerWithToken[removeChangeListenerWithToken({api-pfx}ListenerToken:)] -:url-api-method-replicator-getPendingDocumentIds: {url-api-method-replicator}pendingDocumentIDs[CBLReplicator.pendingDocumentIDs()] +:url-api-method-replicator-getPendingDocumentIds: {url-api-method-replicator}pendingDocumentIDs:[{api-pfx}Replicator.pendingDocumentIDs()] -:url-api-method-replicator-isDocumentPending: {url-api-method-replicator}isDocumentPending[Replicator.isDocumentPending()] +:url-api-method-replicator-isDocumentPending: {url-api-method-replicator}isDocumentPending:error:[{api-pfx}Replicator.isDocumentPending()] :url-api-method-replicator-start: {url-api-properties-replicator}(im)start[start()] @@ -241,7 +237,7 @@ // Meta API :url-api-references-meta: {url-api-references-classes}{api-pfx}QueryMeta.html -:url-api-property-meta-revisionid: {url-api-references-meta}{url-api-references-objc-sep}CBLQueryMeta(cm)revisionID[CBLQueryMeta.revisionID] +:url-api-property-meta-revisionid: {url-api-references-meta}{url-api-references-objc-sep}CBLQueryMeta(cm)revisionID[{api-pfx}QueryMeta.revisionID] diff --git a/modules/swift/examples/code_snippets/SampleCodeTest.swift b/modules/swift/examples/code_snippets/SampleCodeTest.swift index c774daa66..83a7c87b1 100644 --- a/modules/swift/examples/code_snippets/SampleCodeTest.swift +++ b/modules/swift/examples/code_snippets/SampleCodeTest.swift @@ -693,6 +693,45 @@ class SampleCodeTest { // end::replication-status[] } + +// BEGIN PendingDocuments IB -- 11/Feb/21 -- + func dontTestReplicationPendingDocs() throws { + // tag::replication-pendingdocuments[] + + let url = URL(string: "ws://localhost:4984/mydatabase")! + let target = URLEndpoint(url: url) + + let config = ReplicatorConfiguration(database: database, target: target) + config.replicatorType = .push + + // tag::replication-push-pendingdocumentids[] + self.replicator = Replicator(config: config) + let mydocids:Set = self.replicator.pendingDocumentIds() // <.> + + // end::replication-push-pendingdocumentids[] + if(!mydocids.isEmpty) { + print("There are \(mydocids.count) documents pending") + + self.replicator.addChangeListener { (change) in + print("Replicator activity level is \(change.status.activity.toString())") + // iterate and report-on previously + // retrieved pending docids 'list' + for thisId in mydocids.sorted() { + // tag::replication-push-isdocumentpending[] + if(!self.replicator.isDocumentPending(thisid)) { // <.> + print("Doc ID \(thisId) now pushed") + } + // end::replication-push-isdocumentpending[] + } + } + + self.replicator.start() + // end::replication-pendingdocuments[] + } + +// END test PendingDocuments IB -- 11/Feb/21 -- + + func dontTestReplicatorDocumentEvent() throws { // tag::add-document-replication-listener[] let token = self.replicator.addDocumentReplicationListener { (replication) in diff --git a/modules/swift/pages/_partials/_attributes-module.adoc b/modules/swift/pages/_partials/_attributes-module.adoc index 68cc68ebc..fb81b3084 100644 --- a/modules/swift/pages/_partials/_attributes-module.adoc +++ b/modules/swift/pages/_partials/_attributes-module.adoc @@ -183,7 +183,9 @@ :url-api-method-replicator-rmv-change-listener: {url-api-references-replicator}{sep}/s:18CouchbaseLiteSwift10ReplicatorC20removeChangeListener9withTokenyAA0gI0C_tF[removeChangeListener(withToken:)] :url-api-method-replicator-getPendingDocumentIds: {url-api-method-replicator}C18pendingDocumentIdsShySSGyKF[Replicator.pendingDocumentIds()] -:url-api-method-replicator-isDocumentPending: {url-api-method-replicator}C18pendingDocumentIdsShySSGyKF[Replicator.isDocumentPending()] + +[Replicator.pendingDocumentIds()] +:url-api-method-replicator-isDocumentPending: {url-api-method-replicator}C17isDocumentPendingySbSSKF[Replicator.isDocumentPending()] :url-api-method-replicator-start: {url-api-references-replicator}{url-api-references-swift-sep}10ReplicatorC5startyyF[start()]