Concurrent update

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.
For more options, visit https://groups.google.com/groups/opt_out.

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.
For more options, visit https://groups.google.com/groups/opt_out.