Concurrent operations


#1

Hi,

I have a usecase in which I am trying to update the count based on a check. If the check returns false, I do not update the count. This count will be accessed by multiple clients around 100 times/second. Is there a way to achieve this functionality in Couchbase. I have tried using atomic operations, but since I get the value before I increment it the logic fails

JsonLongDocument counter = bucket.counter("counter1",1);
             if (counter.content() < 100) {
                 bucket.upsert(JsonDocument.create("document1", JsonObject.empty().put("name","Document 1").put("count",counter.content())));
             }

Any help will be appreciated.

Thanks,
Samarth


#2

hi @samarthvarshney

I’m not entirely sure I understand what you are trying to achieve… Could you try to describe it in pseudo-code?

Among others, maybe the optimistic locking (CAS, Compare-And-Swap) feature of Couchbase could help you? Something along the lines of getting “document1”, checking the count inside (or another check) and trying to replace the document if check passes, but being prepare for the case where another thread already updated the document (cas() will not match and will throw a CASMismatchException).
Hard to say without more details though…


#3

Hi @simonbasle

I will explain it with an example. I want to keep track of how many times an advertisement is served. When that count reaches a threshold. I will stop publishing the advertisement.

get advertisement_count
if (advertisement_count < threshold){
       increment advertisement_count by 1 and save;
       return advertisement
else
       return null

This code will be executed by around 1000 clients/second. I want to make sure that I stop when the threshold is reached. Also, on using locking, an exception is thrown when the second client tries to save count, which does not suit my usecase. Let me know if you need more info.


#4

ok,
what happens once the advertisement is stopped being published? would clients continuously check the counter (apart from the 1 second window where all of the clients would catch up on the info that threshold has been reached)? or do you track that info elsewhere?

I’m asking because maybe you could use the fact that the increment operation is atomic like so:

long ad_count = increment(ad_count_key, 1) //atomically increment and get count
if (ad_count < THRESHOLD)
    return advertisement
else
    return null

One of the 1000 clients will be the one making ad_count reach the threshold. The remaining 999 clients will still increment the counter but will all detect the threshold is over, so they’d all have catched up on the info that this particular ad has been served enough times and wouldn’t try it or request the ad_count_key again…

Note that this is important they stop trying after first detection that the threshold is passed, since if they continuously try, they continue to increment the counter which will end up overflowing and resetting back to 0…

(in the 2.0 SDK the increment operation would be something like long ad_count = bucket.counter(ad_count_key, 1L).content();)