Skip to content

Commit 9c86d30

Browse files
f1v3-devjhpark816
authored andcommitted
FEATURE: Add CompletableFuture incr, decr API
1 parent 59259c7 commit 9c86d30

3 files changed

Lines changed: 376 additions & 0 deletions

File tree

src/main/java/net/spy/memcached/v2/AsyncArcusCommands.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import net.spy.memcached.ops.CollectionInsertOperation;
6060
import net.spy.memcached.ops.ConcatenationType;
6161
import net.spy.memcached.ops.GetOperation;
62+
import net.spy.memcached.ops.Mutator;
6263
import net.spy.memcached.ops.GetsOperation;
6364
import net.spy.memcached.ops.Operation;
6465
import net.spy.memcached.ops.OperationCallback;
@@ -440,6 +441,70 @@ public void complete() {
440441
return future;
441442
}
442443

444+
445+
public ArcusFuture<Long> incr(String key, int delta) {
446+
return mutate(Mutator.incr, key, delta, -1L, 0);
447+
}
448+
449+
public ArcusFuture<Long> incr(String key, int delta, long initial, int exp) {
450+
if (initial < 0) {
451+
throw new IllegalArgumentException("Initial value must be 0 or greater.");
452+
}
453+
return mutate(Mutator.incr, key, delta, initial, exp);
454+
}
455+
456+
public ArcusFuture<Long> decr(String key, int delta) {
457+
return mutate(Mutator.decr, key, delta, -1L, 0);
458+
}
459+
460+
public ArcusFuture<Long> decr(String key, int delta, long initial, int exp) {
461+
if (initial < 0) {
462+
throw new IllegalArgumentException("Initial value must be 0 or greater.");
463+
}
464+
return mutate(Mutator.decr, key, delta, initial, exp);
465+
}
466+
467+
private ArcusFuture<Long> mutate(Mutator mutator, String key, int delta, long initial, int exp) {
468+
if (delta <= 0) {
469+
throw new IllegalArgumentException("Delta must be greater than 0.");
470+
}
471+
472+
AbstractArcusResult<Long> result = new AbstractArcusResult<>(new AtomicReference<>());
473+
ArcusFutureImpl<Long> future = new ArcusFutureImpl<>(result);
474+
ArcusClient client = arcusClientSupplier.get();
475+
476+
OperationCallback cb = new OperationCallback() {
477+
@Override
478+
public void receivedStatus(OperationStatus status) {
479+
switch (status.getStatusCode()) {
480+
case SUCCESS:
481+
result.set(Long.parseLong(status.getMessage()));
482+
break;
483+
case ERR_NOT_FOUND:
484+
result.set(-1L);
485+
break;
486+
case CANCELLED:
487+
future.internalCancel();
488+
break;
489+
default:
490+
// TYPE_MISMATCH or unknown statement
491+
result.addError(key, status);
492+
break;
493+
}
494+
}
495+
496+
@Override
497+
public void complete() {
498+
future.complete();
499+
}
500+
};
501+
Operation op = client.getOpFact().mutate(mutator, key, delta, initial, exp, cb);
502+
future.setOp(op);
503+
client.addOp(key, op);
504+
505+
return future;
506+
}
507+
443508
public ArcusFuture<Map<String, CASValue<T>>> multiGets(List<String> keys) {
444509
ArcusClient client = arcusClientSupplier.get();
445510
Collection<Map.Entry<MemcachedNode, List<String>>> arrangedKeys

src/main/java/net/spy/memcached/v2/AsyncArcusCommandsIF.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,52 @@ public interface AsyncArcusCommandsIF<T> {
143143
*/
144144
ArcusFuture<Map<String, T>> multiGet(List<String> keys);
145145

146+
/**
147+
* Increments a numeric value stored at the given key by {@code delta}.
148+
*
149+
* @param key the key
150+
* @param delta the amount to increment (&gt; 0)
151+
* @return the new value after increment, or -1 if the key is not found
152+
*/
153+
ArcusFuture<Long> incr(String key, int delta);
154+
155+
/**
156+
* Increments a numeric value stored at the given key by {@code delta}.
157+
* If the key does not exist,
158+
* it is created with the value of {@code initial} and expiration time of {@code exp}.
159+
*
160+
* @param key the key
161+
* @param delta the amount to increment (&gt; 0)
162+
* @param initial the value to store if the key does not exist ({@code delta} is ignored) (&ge; 0)
163+
* @param exp expiration time in seconds, applied only when a new key is created
164+
* @return the new value after increment, or {@code initial} if the key did not exist
165+
*/
166+
ArcusFuture<Long> incr(String key, int delta, long initial, int exp);
167+
168+
/**
169+
* Decrements a numeric value stored at the given key by {@code delta}.
170+
* <p>If the value is decremented below 0, it will be set to 0.</p>
171+
*
172+
* @param key the key
173+
* @param delta the amount to decrement (&gt; 0)
174+
* @return the new value after decrement, or -1 if the key is not found
175+
*/
176+
ArcusFuture<Long> decr(String key, int delta);
177+
178+
/**
179+
* Decrements a numeric value stored at the given key by {@code delta}.
180+
* If the key does not exist,
181+
* it is created with the value of {@code initial} and expiration time of {@code exp}.
182+
* <p>If the value is decremented below 0, it will be set to 0.</p>
183+
*
184+
* @param key the key
185+
* @param delta the amount to decrement (&gt; 0)
186+
* @param initial the value to store if the key does not exist ({@code delta} is ignored) (&ge; 0)
187+
* @param exp expiration time in seconds, applied only when a new key is created
188+
* @return the new value after decrement, or {@code initial} if the key did not exist
189+
*/
190+
ArcusFuture<Long> decr(String key, int delta, long initial, int exp);
191+
146192
/**
147193
* Get values with CAS for multiple keys.
148194
*

0 commit comments

Comments
 (0)