# Concurrent update

**URL:** <https://discuss.elastic.co/t/concurrent-update/11606>\
**Category:** Elasticsearch\
**Created:** [April 16, 2013, 11:44pm UTC](https://discuss.elastic.co/t/concurrent-update/11606 "2013-04-16T23:44:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Thomas\_Meson](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/thomas_meson/32/2359_2.png) [@Thomas\_Meson](https://discuss.elastic.co/u/Thomas_Meson)\
**Post date:** [April 16, 2013, 11:44pm UTC](https://discuss.elastic.co/t/concurrent-update/11606/1 "2013-04-16T23:44:46Z")

</div>

Hi,

I'm currently facing a problem using ES.  
I'm trying to implement something like a "wallet balance count" that I  
decrement.

My API calls ES to decrement this counter, and take different actions when  
this counter pass under 0.  
Problem is, those calls to the API/ES can be concurrent.  
So, I can quickly run into a race condition.  
I'm using a script in the \_update to detect when the balance passes under  
0. (if (ctx.\_source.?credits != null && (ctx.\_source.credits - cred) \>= 0)  
{ ctx.\_source.credits = ctx.\_source.credits - cred } else { ctx.op =  
"none" } .. where cred is the credit I want to substract)  
But I can't find a way to make the script fail in a if condition.  
I know that ES handles all concurrency/retries by itself, my problem is, I  
can't find a way to know if an update actually occured.  
With the ctx.op = "none" in my script, this works, the version is not  
incremented, but the problem is still the same, I don't know if the update  
worked or no (actually updated the field or not).  
Something that would help to go around this, would be to have  
"field\_scripts", that allow me to compute the "expected" value, and compare  
it to the actual "updated or not" value.  
(ie, my balance is 5, I try to decrement 6, so my script doesn't update the  
value, but the "field\_script" tells me -1).  
And a final solution is see is to implement manually the STM that ES has,  
meaning get the document version before, perform the update, if the version  
doesn't change or actual-prev \> 1, retry.

tl;dr: is there any way to know if an \_update actually performed the  
update, and has incremented the version.

What kind of solution you have for this use case ?

--  
You received this message because you are subscribed to the Google Groups "elasticsearch" group.  
To unsubscribe from this group and stop receiving emails from it, send an email to [elasticsearch+unsubscribe@googlegroups.com](mailto:elasticsearch+unsubscribe@googlegroups.com).  
For more options, visit [https://groups.google.com/groups/opt\_out](https://groups.google.com/groups/opt_out).

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [April 18, 2013, 7:23pm UTC](https://discuss.elastic.co/t/concurrent-update/11606/2 "2013-04-18T19:23:31Z")

</div>

A few solutions comes to mind. You can try throwing an exception in your  
script. I don't think MVEL allows throwing exceptions from the code, but  
you can switch to a different scripting language, use native script, or in  
worst case just trigger exception by doing something like this ()[0];  
Another solution is to assign each transaction a unique id and keep track  
of transaction history in the record. After running the update operation  
you can retrieve the record again to check if transaction id for the  
current transaction is present in the transactions list.

The best solution, in my opinion, would be to handle it on the client side.  
The update API is just a connivence method. You can implement the same  
retry on version conflict logic on the client side. This way you will have  
complete control over failure scenarios.

On Tuesday, April 16, 2013 7:44:46 PM UTC-4, Thomas Meson wrote:

> Hi,
> 
> I'm currently facing a problem using ES.  
> I'm trying to implement something like a "wallet balance count" that I  
> decrement.
> 
> My API calls ES to decrement this counter, and take different actions when  
> this counter pass under 0.  
> Problem is, those calls to the API/ES can be concurrent.  
> So, I can quickly run into a race condition.  
> I'm using a script in the \_update to detect when the balance passes under  
> 0. (if (ctx.\_source.?credits != null && (ctx.\_source.credits - cred) \>= 0)  
> { ctx.\_source.credits = ctx.\_source.credits - cred } else { ctx.op =  
> "none" } .. where cred is the credit I want to substract)  
> But I can't find a way to make the script fail in a if condition.  
> I know that ES handles all concurrency/retries by itself, my problem is, I  
> can't find a way to know if an update actually occured.  
> With the ctx.op = "none" in my script, this works, the version is not  
> incremented, but the problem is still the same, I don't know if the update  
> worked or no (actually updated the field or not).  
> Something that would help to go around this, would be to have  
> "field\_scripts", that allow me to compute the "expected" value, and compare  
> it to the actual "updated or not" value.  
> (ie, my balance is 5, I try to decrement 6, so my script doesn't update  
> the value, but the "field\_script" tells me -1).  
> And a final solution is see is to implement manually the STM that ES has,  
> meaning get the document version before, perform the update, if the version  
> doesn't change or actual-prev \> 1, retry.
> 
> tl;dr: is there any way to know if an \_update actually performed the  
> update, and has incremented the version.
> 
> What kind of solution you have for this use case ?

--  
You received this message because you are subscribed to the Google Groups "elasticsearch" group.  
To unsubscribe from this group and stop receiving emails from it, send an email to [elasticsearch+unsubscribe@googlegroups.com](mailto:elasticsearch+unsubscribe@googlegroups.com).  
For more options, visit [https://groups.google.com/groups/opt\_out](https://groups.google.com/groups/opt_out).

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 6, 2017, 2:40am UTC](https://discuss.elastic.co/t/concurrent-update/11606/3 "2017-07-06T02:40:36Z")

</div>


