diff --git a/samples/snippets/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java b/samples/snippets/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java index 8c6d3a220..ad4ac19b4 100644 --- a/samples/snippets/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java +++ b/samples/snippets/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java @@ -20,13 +20,17 @@ import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; import com.google.cloud.firestore.CollectionReference; +import com.google.cloud.firestore.DocumentReference; import com.google.cloud.firestore.DocumentSnapshot; import com.google.cloud.firestore.Firestore; import com.google.cloud.firestore.Query; import com.google.cloud.firestore.Query.Direction; import com.google.cloud.firestore.QueryDocumentSnapshot; import com.google.cloud.firestore.QuerySnapshot; +import com.google.cloud.firestore.TransactionOptions; import com.google.cloud.firestore.WriteResult; +import com.google.protobuf.Timestamp; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -591,7 +595,53 @@ Query filterNotIn() { return query; } - /** Closes the gRPC channels associated with this instance and frees up their resources. */ + /** + * Run stale reads. Demonstrate a document lookup and a query. + * + * @return DocumentSnapshot documentResult + */ + DocumentSnapshot runStaleReads() throws Exception { + // [START firestore_stale_read] + // Create a read time 15 seconds in the past + Instant now = Instant.now(); + final int fifteenSeconds = 15; + final Timestamp readTime = Timestamp.newBuilder() + .setSeconds(now.getEpochSecond() - fifteenSeconds) + .setNanos(now.getNano()).build(); + + // Set transaction options. Use read-only and set read time + // Stale reads require a read-only transaction + TransactionOptions options = TransactionOptions + .createReadOnlyOptionsBuilder() + .setReadTime(readTime).build(); + + // Create a document reference + final DocumentReference documentReference = db + .collection("cities") + .document("SF"); + + // Create a query against the cities collection. + Query query = db.collection("cities").whereEqualTo("capital", true); + + // run a transaction with the specified transaction options + ApiFuture futureTransaction = db + .runTransaction(transaction -> { + // Execute a stale read document lookup + final DocumentSnapshot documentResult = transaction + .get(documentReference).get(); + + // Execute a stale read query + final QuerySnapshot queryResult = transaction.get(query).get(); + + return documentResult; + }, options); + // [END firestore_stale_read] + return futureTransaction.get(); + } + + /** + * Closes the gRPC channels associated with this instance and frees up their resources. + */ void close() throws Exception { db.close(); } diff --git a/samples/snippets/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java b/samples/snippets/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java index 128a8c54c..50135fdcb 100644 --- a/samples/snippets/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java +++ b/samples/snippets/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java @@ -18,6 +18,7 @@ import static com.google.common.collect.Sets.newHashSet; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import com.example.firestore.BaseIntegrationTest; @@ -271,6 +272,13 @@ public void testFilterNotIn() throws Exception { assertEquals(expected, actual); } + @Test + public void testSnapshotReads() throws Exception { + // Verify that this runs without error + DocumentSnapshot doc = queryDataSnippets.runStaleReads(); + assertNotNull("should not be null", doc); + } + private Set getResultsAsSet(Query query) throws Exception { List docIds = getResults(query); return new HashSet<>(docIds);