Search code examples
javaconcurrencyazure-cosmosdbetag

Simultaneous Cosmos document creation


I am getting a race condition when trying to update (here creating the document for the first time) to Cosmos with the same primary key and part key simultaneously, and as a result, I am losing one of the updates. The business logic is to update the document if it already exists and create it if it does not exist, but losing some data if two creations occur at the same timestamp. I know we can achieve concurrency using eTag, but here the issue happens only for the first update or creation of a document.

For example, consider the following models: { "id": 1, "pkey": 2, "value": ["first text"]} and

{ "id": 1, "pkey": 2, "value": ["second text"]} I have some internal business logic to update and append the value array. { "id": 1, "pkey": 2, "value": ["first text," "second text,"] } But I lose one value when cosmos creation occurs simultaneously. Please feel free to correct the question if any errors are found.

Please help if anyone has faced a similar issue. tried keeping etag in the request option, but the issue still persists.


Solution

  • Based on your description it looks like you are executing concurrent Replaces over existing documents.

    The best way to avoid the scenario where a second concurrent Replace removed the data added by the first is to use Optimistic Concurrency.

    In a nutshell:

    1. Read the document you want to update.
    2. From the response, you obtain the ETag.
    3. Apply modification locally and send the Replace operation with the IfMatchETag option.
    4. If there was a concurrent Replace operation, you will get an HTTP 412 response.
    5. Repeat 1-4 until you get a success response.

    Full example from the Java SDK (assuing Java because your question is tagged so) repo: https://github.com/Azure-Samples/azure-cosmos-java-sql-api-samples/blob/0ead4ca33dac72c223285e1db866c9dc06f5fb47/src/main/java/com/azure/cosmos/examples/documentcrud/async/DocumentCRUDQuickstartAsync.java#L405