I'm using go with etcd as DB and trying to have transactions for atomic counter. I need to have a transaction with 2 pre-conditions:
- some key exists i.e:
clientv3.Compare(clientv3.Version(wantedKey), "!=", 0)
- counter is less than some
maxVal
i.e:clientv3.Compare(clientv3.Value(counterKey), "<", maxVal)
The problem is at the If()
call, I would like to increment / decrement that counter on the same transactions, instead of having 1st getCounterVal
txn and 2nd inc/decCounterVal
(you know.. like compareAndSet
) txn..
Does anybody knows how to do it? is 2 txn's with loops on compareAndSet()
is the only way?
Yes unfortunately (and surprisingly) etcd does not seem to provide any atomic inc/dec operations. It seems the only way is to do two seperate transactions, first one to read the current value and then a transaction which has the two comparisons plus a check on the version of the key and if all 3 checks pass, put the incremented value.
And as you said, you will need to do this in a loop because concurrent clients might have changed the value between the first transaction (Read) and the second (CompareAndSet)
It's a quite inefficient way to handle counters. An Inc or Dec op would make many things much easier but there is only Put and it can't reference anything, just carry a specified value.
See also this Github issue: https://github.com/etcd-io/etcd/issues/9714