0
votes

I have a REST API server that triggers some operations on my NoSQL Cosmos database

My script has this pattern: 1. create collection 2. write 20 documents to the new collection 3. query the collection (and verify query) 4. delete the collection

I boot up my REST server and make the API calls to do the 4 steps above. Everything works fine the first time. While the same server is running, when I try to do the 4 steps above a second time I get this error when doing the querying part (step 3):

com.microsoft.azure.documentdb.DocumentClientException: Message: {"Errors":["The requested resource is no longer available at the server."]} ActivityId: ba46f15a-3615-4764-adea-419c17d26c8e, Request URI: /apps/91dbada6-1498-4f1b-b8ae-047db532568d/services/66113bcb-793b-4d5b-ab9d-6ad5738cda30/partitions/0c2487d2-a50c-4ea5-9859-b61335b06c25/replicas/132049092719729780s/, RequestStats: RequestStartTime: 2019-06-14T18:50:41.0726964Z, RequestEndTime: 2019-06-14T18:50:41.0726964Z, Number of regions attempted: 1 ResponseTime: 2019-06-14T18:50:41.0726964Z, StoreResult: StorePhysicalAddress: rntbd://cdb-ms-prod-eastus1-fd28.documents.azure.com:16711/apps/91dbada6-1498-4f1b-b8ae-047db532568d/services/66113bcb-793b-4d5b-ab9d-6ad5738cda30/partitions/0c2487d2-a50c-4ea5-9859-b61335b06c25/replicas/132049092719729780s/, LSN: 25, GlobalCommittedLsn: 24, PartitionKeyRangeId: , IsValid: True, StatusCode: 410, SubStatusCode: 1000, RequestCharge: 0, ItemLSN: -1, SessionToken: -1#21, UsingLocalLSN: True, TransportException: null, ResourceType: Document, OperationType: Query , SDK: Microsoft.Azure.Documents.Common/2.4.0.0, StatusCode: InvalidPartition

'''

public void createDocumentCollectionIfNotExists(String databaseName, String collectionName) throws Exception {
    String databaseLink = String.format("/dbs/%s", databaseName);
    String collectionLink = String.format("/dbs/%s/colls/%s", databaseName, collectionName);

    try {
        this.client.readCollection(collectionLink, null);
        System.out.println(String.format("Found %s", collectionName));
    } catch (DocumentClientException de) {
        if (de.getStatusCode() == 404) {
            DocumentCollection collectionInfo = new DocumentCollection();
            collectionInfo.setId(collectionName);

            RequestOptions requestOptions = new RequestOptions();
            requestOptions.setOfferThroughput(400);

            this.client.createCollection(databaseLink, collectionInfo, requestOptions);
        } else {
            throw de;
        }
    }
}

'''

public String queryCollection(String databaseName, String collectionName) {
    FeedOptions queryOptions = new FeedOptions();
    queryOptions.setEnableCrossPartitionQuery(true);
    queryOptions.setMaxDegreeOfParallelism(-1);

    String collectionLink = String.format("/dbs/%s/colls/%s", databaseName, collectionName);
    System.out.println(collectionLink);

    Iterable<Document> queryResults = client.queryDocuments(
            collectionLink,
            String.format(baseQuery, collectionName),
            queryOptions).getQueryIterable();

    return buildJsonList(queryResults);
}

'''

public int createDocument(String databaseName, String collectionName, EventDocument document) throws DocumentClientException {
    System.out.println("trying to write to database");
    String collectionLink = String.format("/dbs/%s/colls/%s", databaseName, collectionName);

    ResourceResponse<Document> response = client.createDocument(collectionLink, document, new RequestOptions(), false);

    return response.getStatusCode();
}
2
Which SDK version are you using? Are you using the same name when you delete and create?Matias Quaranta
I'm using the latest one 2.1.3. Yes, I'm using the same name when I delete and create. When I randomize the database name it seems to work just fine... is that the problem?knownastron
Hi,does my answer helps you?Jay Gong

2 Answers

0
votes

Try to reproduce your issue but failed,please view my test code:

public class Test {

    static private String YOUR_COSMOS_DB_ENDPOINT = "https://***.documents.azure.com:443/";
    static private String YOUR_COSMOS_DB_MASTER_KEY = "***";

    static DocumentClient client = new DocumentClient(
            YOUR_COSMOS_DB_ENDPOINT,
            YOUR_COSMOS_DB_MASTER_KEY,
            new ConnectionPolicy(),
            ConsistencyLevel.Session);

    public static void main(String[] args) throws Exception {

        createDocumentCollectionIfNotExists("db", "test");

        for (int i = 1; i <= 10; i++) {
            Document document = new Document();
            document.set("id", i + "");
            createDocument("db", "test", document);
        }
        queryCollection("db", "test");

        deleteCollection("db", "test");

    }

    public static void createDocumentCollectionIfNotExists(String databaseName, String collectionName) throws Exception {
        String databaseLink = String.format("/dbs/%s", databaseName);
        String collectionLink = String.format("/dbs/%s/colls/%s", databaseName, collectionName);

        try {
            client.readCollection(collectionLink, null);
            System.out.println(String.format("Found %s", collectionName));
        } catch (DocumentClientException de) {
            if (de.getStatusCode() == 404) {
                DocumentCollection collectionInfo = new DocumentCollection();
                collectionInfo.setId(collectionName);

                RequestOptions requestOptions = new RequestOptions();
                requestOptions.setOfferThroughput(400);

                client.createCollection(databaseLink, collectionInfo, requestOptions);
            } else {
                throw de;
            }
        }
    }

    public static void queryCollection(String databaseName, String collectionName) {
        FeedOptions queryOptions = new FeedOptions();
        queryOptions.setEnableCrossPartitionQuery(true);
        queryOptions.setMaxDegreeOfParallelism(-1);

        String collectionLink = String.format("/dbs/%s/colls/%s", databaseName, collectionName);
        System.out.println(collectionLink);

        Iterable<Document> queryResults = client.queryDocuments(
                collectionLink,
                String.format("select * from c", collectionName),
                queryOptions).getQueryIterable();
        for (Document doc : queryResults) {
            System.out.println(doc.getId());
        }
    }


    public static int createDocument(String databaseName, String collectionName, Document document) throws DocumentClientException {
        System.out.println("trying to write to database ,id: " + document.get("id"));
        String collectionLink = String.format("/dbs/%s/colls/%s", databaseName, collectionName);

        ResourceResponse<Document> response = client.createDocument(collectionLink, document, new RequestOptions(), false);

        return response.getStatusCode();
    }


    public static void deleteCollection(String databaseName, String collectionName) throws DocumentClientException {
        FeedOptions queryOptions = new FeedOptions();
        queryOptions.setEnableCrossPartitionQuery(true);
        queryOptions.setMaxDegreeOfParallelism(-1);

        String collectionLink = String.format("/dbs/%s/colls/%s", databaseName, collectionName);
        System.out.println(collectionLink);

        client.deleteCollection(collectionLink, null);

        System.out.println("delete......collection....");
    }
}

My sdk version is:

 <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-documentdb</artifactId>
        <version>2.4.0</version>
 </dependency>

Output:

enter image description here

The error:

"Errors":["The requested resource is no longer available at the server."]}

because the collection you want to query doesn't exist. If you execute sequentially, you won't have this issue. If you have parallel needs, just add some try-catch block or some logical code to trace this exception(e.g. judge the collection if exists.)

0
votes

This looks like a cache issue. The SDK has an internal cache for address resolution, that gets updated as operations happen.

In older versions, there could be an issue if the collection you were operating got recreated with the same name, by an external source (if the delete is done by the SDK, it's not an issue). You mentioned in the comments you are on 2.1.3, but the latest, according to Maven, is 2.4.0.

If updating is not an option, a retry on this exception should do the trick as the address caches should be updated after the first error occurs.