Concurrency n1ql issues - CAS

DOCUMENT#1
{
“id”: 1,
“sessionId” : “XFFDFDFD2232”,

“products”: [
{
“id”: 1,
“basketId” :2323232,
“code” : “A23232”,
“qty” : 5,
“mode” :1

},
 {
  "id": 1,
  "basketId" :535353,
  "code" : "23232FFD",
  "qty" : 15,
  "mode" :2

},
 {
  "id": 1,
  "basketId" :75565,
  "code" : "43432FDFD",
  "qty" : 25,
  "mode" :1

},
 {
  "id": 1,
  "basketId" :87878,
  "code" : "DSKD343",
  "qty" : 1,
  "mode" :1

},
 {
  "id": 1,
  "basketId" :2121,
  "code" : "REIURE",
  "qty" : 200,
  "mode" :1

},
 {
  "id": 1,
  "basketId" :54354,
  "code" : "FHJDF",
  "qty" : 5,
  "mode" :1

}
]

}

We have document in above format. Initially when we designed we expected (delete of nested documents in single calls with combination of one id and basketid
So it was working fine. But now there is a possiblity of parallel calls upto 5 to our API.

Say eg. Call#1 (id & basketId ) 1, 2323232
Call#2 (id & basketId ) 1, 535353
Call#3 (id & basketId ) 1, 2121

Sometimes all three record gets deleted and sometimes only 1 get deleted. Later we realized parallel calls is causing this issue as these three calls
updating the same document.

We are using Update statement to delete the nested document that matches the condtion using ARRAY_REMOVE with filters on basketId and parent document id

how to handle this scenario so that all the three records should get deleted. I looked into CAS and getAndLock but not able get it correctly.

Please advise. Thanks

Each UPDTE statement is different. You must have retry logic of CAS mismatch to protect from parallel statements mutating same document.

1.     Combine all 3 and use single UPDATE statement.
2.     Serialize the UPDATE from your API
3.     Issue separate UPDATE statement and if CAS mismatch retry the UPDATE until succeed.
4.     If you already know document id use SDK subdoc API. As each parallel one goes as separate you must do same CAS check and retry,

Thank you I will check. Do you have any samples for the option#3&4. Thanks

@y2k1975 I don’t think you can use Sub-Document key-value API with your present document model, as that doesn’t have any functionality similar to “ARRAY_REMOVE with filters on basketId and parent document id”.
If you could change your document model so that products was a JSON object rather than an array, with the key in that object being “_” e.g. “1-87878”, then you could use Sub-Document then. An example could look like:

collection.mutateIn(documentId, Arrays.asList( MutateInSpec.remove(documentId + "_" + basketIdsToRemove[0]), MutateInSpec.remove(documentId + "_" + basketIdsToRemove[1])));

Nb this assumes that you don’t care if multiple actors try to remove the same basketIds at the same time, you just want that to succeed. Which I think is what you’re aiming for?

1 Like

Thank you we considered to have format with key value pair some thing like this

“products”: {
“75565” : {
“id”: 1,
“basketId” :75565,
“code” : “43432FDFD”,
“qty” : 25,
“mode” :1,
“type” : “A”

},
“87878”: {
“id”: 1,
“basketId” :87878,
“code” : “DSKD343”,
“qty” : 1,
“mode” :1
“type” : “A”
},
“72323”: {
“id”: 1,
“basketId” :72323,
“code” : “ABDS”,
“qty” : 1,
“mode” :1
“type” : “B”
}
}

But that needs to go for schema changes and that gets into changes for existing code especially we have select query in existing model that will return only the products for specific type and the format was as shown below. Not sure how to get the same using the above updated schema.

“products” : [
{
“id”: 1,
“basketId” :75565,
“code” : “43432FDFD”,
“qty” : 25,
“mode” :1,
“type” : “A”

},
{
“id”: 1,
“basketId” :75565,
“code” : “43432FDFD”,
“qty” : 25,
“mode” :1,
“type” : “A”
}
]

Changing the structure helped to achieve it. Thanks

1 Like